How to ensure read-only variables and maps in golang

huangapple go评论80阅读模式
英文:

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 How to ensure read-only variables and maps in golang

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.

huangapple
  • 本文由 发表于 2023年2月4日 22:36:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75345799.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定