英文:
How to ensure read-only variables and maps in golang
问题
我希望我的程序可以访问全局的只读正则表达式和映射。以下是我考虑的方法:
var myRegex *regexp.Regexp
var myMap map[string]string
func init() {
myRegex = regexp.MustCompile("blah")
myMap = map[string]string{"blah": "blah"}
}
或者我可以这样做:
type myStruct struct {
// 已经有了其他一堆结构字段
myRegex *regexp.Regexp
myMap map[string]string
}
func Initialize() *myStruct {
m := myStruct{
// 其他一堆东西
myRegex: regexp.MustCompile("blah"),
myMap: map[string]string{"blah": "blah"},
}
return &m
}
但是我如何确保这些变量不会被我的软件的任何其他部分写入?
英文:
I want my programs have access to global read-only regex and maps. Here's what i thought of :
var myRegex *regexp.Regexp
var myMap map[string]string
func init() {
myRegex = regexp.MustCompile("blah")
myMap = map[string]string{"blah": "blah"}
}
or i can do
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"}
}
But how i can ensure that these variables won't be writable by any other piece of my software ?
答案1
得分: 1
只要你处理指针(映射本身就是指针),你就无法确保你的映射或正则表达式是只读的。
(好吧,除非你每次都用函数复制值并返回一个新的指针...但我不确定这是否是你想要实现的:)
如果我拿你的例子,并添加一个简单的主要代码:
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)
}
你可以看到我可以修改映射:
❯ ./main
map[blah:blah]
map[blah:blah blah2:blah2]
map[blah:blah blah2:blah2]
map[blah:blah]
map[blah:blah test:test]
正则表达式仍然是完全相同的。
如果你真的想确保你的正则表达式和映射永远不会被其他代码错误地更新,有几种解决方案;其中大部分是将只读变量移动到自己的包中,并且永远不直接访问它们。例如,像这样:
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",
},
}
然后在需要的其他文件中导入此包。
但正如我所说,你的问题缺乏一些上下文,以确保答案符合你的期望。
英文:
As long as you're dealing with pointers ( maps are pointers anyway ), you' ll never be able to ensure that your map or regex is ReadOnly.
( Ok, unless you copy the value with the function each time and return a new pointer... But i'm not sure that's what you want to achieve
If i take your example, and add a simple main code :
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)
}
you see that i can modify the maps:
❯ ./main
map[blah:blah]
map[blah:blah blah2:blah2]
map[blah:blah blah2:blah2]
map[blah:blah]
map[blah:blah test:test]
Regex would be exactly the same.
If you really want to ensure that your regex and maps will never be updated by mistake by another piece of code, there's couple of solutions; most of them consisting of moving your read-only variables in there own package and never give direct access to them. Something like this for instance
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",
},
}
and then import this package in your other files that requires it.
But as said, your question is lacking a bit of context to ensure that the answer is what your expect.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论