如何在Go中使用未共享的有状态变量?

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

How to have unshared stateful variables in Go?

问题

我知道,现在(可能永远)Go语言中没有静态变量...但是有没有一种方法可以保护变量呢?

import (
    "net/http"
    "net/http/cookiejar"
)

func funcThatDoesRequests(request Request) (response Response, e error){
  static cookieJar, _ := cookiejar.New(nil)
  static client := http.Client{ Jar: cookieJar }
  response, e = client.Do(handshakeRequest)
  return
}

我不希望http的client和它的cookieJar在其他函数中随意使用。我需要cookieJarclient只能在funcThatDoesRequests函数内部访问。这可能吗?

静态变量(在伪代码示例中使用static关键字)是一种在C和PHP等语言中常见的特性。

英文:

I know that, right now (and probably forever), we won't have static variables in Go... but is there a way to protect variables in some way?

import (
    "net/http"
    "net/http/cookiejar"
)

func funcThatDoesRequests(request Request) (response Response, e error){
  static cookieJar, _ := cookiejar.New(nil)
  static client := http.Client{ Jar: cookieJar }
  response, e = client.Do(handshakeRequest)
  return
}

I don't want the http client and its cookieJar floating around so other functions can do something with them. I need the cookieJar and client to only be accessible inside the funcThatDoesRequests. Is that possible?

> Static variables (see static keyword in the pseudo code example) is a feature present in languages like C and PHP, to name some common languages.

答案1

得分: 3

通常最好不要担心包范围的全局变量,因为只有你自己包中的代码才能滥用它们。

但是如果你真的想要,你可以使用闭包,在加载你的包时创建“静态”变量。

func makeFunc() func(req Request)(Response, error) {
    cookieJar, _ := cookiejar.New(nil)
    client := http.Client{Jar: cookieJar}
    return func(req Request)(Response, error) {
        return client.Do(handshakeRequest)
    }
}

var funcThatDoesRequests = makeFunc()

现在,funcThatDoesRequests 在多次调用中保持了 clientcookieJar,但是这些名称不会泄露到包外。

英文:

Usually it's best not to worry about package-scoped globals since it's only code in your own package that can abuse them.

But if you really want, you can use a closure which is created when your package is loaded to generate the "static" variables.

func makeFunc() func(req Request)(Response, error) {
    cookieJar, _ := cookiejar.New(nil)
    client := http.Client{Jar: cookieJar}
    return func(req Request)(Response, error) {
        return client.Do(handshakeRequest)
    }
}

var funcThatDoesRequests = makeFunc()

Now funcThatDoesRequests maintains client and cookieJar over multiple calls, but the names don't leak into the package.

答案2

得分: 1

一种可能的方法是创建一个包含“私有静态”变量的结构体,并将处理程序作为该结构体的方法。

type privateData struct {
    jar    *cookiejar.Jar
    client http.Client
}

func (r *privateData) Initialize() {
    r.jar = cookiejar.New(nil)
    r.client = http.Client{Jar: r.jar}
}

func (r *privateData) Do(request Request) (response Response, e error) {
    /* 其余的代码放在这里 */
}

/* 然后,在某个地方... */
var thing privateData
thing.Initialize()
/* 然后,您可以将 thing.Do 传递给原本需要传递 funcThatDoesRequests 的地方 */
英文:

One possibility would be to create a struct with your "private, static" variables and make your handler a method of that struct.

type privateData struct {
    jar *cookiejar.Jar
    client http.Client
}

func (r *privateData) Initialize() {
    r.jar = cookiejar.New(nil)
    r.client = http.Client{Jar: r.jar}
}

func (r *privateData) Do (request Request) (response Response, e error) {
    /* Rest of the code goes here */
}

/* then, somewhere... */
var thing privateData
thing.Initialize()
/* then you can pass thing.Do where you would have passed funcThatDoesRequests */

huangapple
  • 本文由 发表于 2014年12月1日 18:03:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/27225898.html
匿名

发表评论

匿名网友

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

确定