Go语言 在结构体中还是单独定义全局只读变量?[已关闭]

de90aj5v  于 2023-02-06  发布在  Go
关注(0)|答案(1)|浏览(172)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新此问题,以便editing this post可以用事实和引文来回答。

昨天关门了。
Improve this question
我的程序有全局正则表达式和全局只读Map,我可以像这样将它们定义为全局变量,也可以定义在一个结构体中(不是一个新的结构体,而是已经存在的结构体,它有很多方法可以访问全局变量)。
具体来说我可以

var myRegex *regexp.Regexp
var myMap map[string]string

func init() {
    myRegex = regexp.MustCompile("blah")
    myMap = map[string]string{"blah": "blah"}
}

或者我可以

type myStruct struct {
    //  already have bunch of other struct fields
    myRegex    *regexp.Regexp
    myMap map[string]string
}

func Initialize() *myStruct {
    m := myStruct {
        // bunch of other stuff
        myRegex: regexp.MustCompile("blah")
        myMap: map[string]string{"blah": "blah"}
}

我也看到了一个关于只读Map的模式。我想我可以使用类似的函数来保护正则表达式也是只读的。

func getMyMap() {
   return map[string]string{"blah": "blah"}
}

我应该遵循哪种模式?为什么?

06odsfpq

06odsfpq1#

只要你在处理指针(反正map也是指针),你就永远无法确保你的map或regex是只读的。
(好吧,除非你每次都用函数复制值并返回一个新指针......但我不确定这是你想要达到的目的:)
如果我拿你的例子,并添加一个简单的主代码:

package main

import (
    "fmt"
    "regexp"
)

var myRegex *regexp.Regexp = regexp.MustCompile("blah")
var myMap map[string]string

func init() {
    myRegex = regexp.MustCompile("blah")
    myMap = map[string]string{"blah": "blah"}
}

type myStruct struct {
    //  already have bunch of other struct fields
    myRegex *regexp.Regexp
    myMap   map[string]string
}

func Initialize() myStruct {
    return myStruct{
        // bunch of other stuff
        myRegex: regexp.MustCompile("blah"),
        myMap:   map[string]string{"blah": "blah"},
    }
}

func getMap() map[string]string {
    return myMap
}

func main() {
    fmt.Println(myMap)
    myMap["blah2"] = "blah2"
    fmt.Println(myMap)
    fmt.Println(getMap())

    m := Initialize()

    fmt.Println(m.myMap)
    m.myMap["test"] = "test"
    fmt.Println(m.myMap)
}

你看我可以修改Map:

❯ ./main
map[blah:blah]
map[blah:blah blah2:blah2]
map[blah:blah blah2:blah2]
map[blah:blah]
map[blah:blah test:test]

正则表达式将完全相同。
如果你真的想确保你的正则表达式和Map永远不会被另一段代码错误地更新,有两个解决方案;大多数方法都是把你的只读变量移到你自己的包里,并且永远不给予直接访问它们的权限。

package mapreadonly

type ReadOnlyMap struct {
    m map[string]string
}

func (elem ReadOnlyMap) Get(key string) (string, bool) {
    value, ok := elem.m[key]
    return value, ok
}

var Map1 ReadOnlyMap = ReadOnlyMap{
    m: map[string]string{
        "blah": "blah",
    },
}

然后将此包导入到需要它的其他文件中。
但正如所言,您的问题缺少一点上下文,无法确保答案是您所期望的。

相关问题