简体   繁体   中英

Golang constant struct key

In PHP we can do something like:

if ($env == "dev") 
  define("key", "key")
else
  define("key", "secret")

// json ouput
//{ key : "value" } or { secret : "value" }

How do I properly translate above PHP approach to GO?

I was thinking of something like:

if *env == "dev" {
  type response struct {
    key string
    ...50 more keys that should also be different depending on env
  }
} else {
    secret string
    ...50 more keys...
}

But I guess that is not only wrong but would also create a huge repeated code...

You may create a struct type holding the common part of your data structure, and you may create new types embedding this and only adding the deviating new field. So there is no code repetition of the common part of the data structure:

type Response struct {
    F1 string
    F2 int
}

func main() {
    for _, env := range []string{"dev", "prod"} {
        if env == "dev" {
            type Resp struct {
                Response
                Key string
            }
            r := Resp{Response{"f1dev", 1}, "value"}
            json.NewEncoder(os.Stdout).Encode(r)
        } else {
            type Resp struct {
                Response
                Secret string
            }
            r := Resp{Response{"f1pro", 2}, "value"}
            json.NewEncoder(os.Stdout).Encode(r)
        }
    }
}

Output (try it on the Go Playground ):

{"F1":"f1dev","F2":1,"Key":"value"}
{"F1":"f1pro","F2":2,"Secret":"value"}

Note that you may also use the same Response value if they are the same for the 2 use cases:

comResp := Response{"f1value", 1}
if env == "dev" {
    type Resp struct {
        Response
        Key string
    }
    r := Resp{comResp, "value"}
    json.NewEncoder(os.Stdout).Encode(r)
} else {
    type Resp struct {
        Response
        Secret string
    }
    r := Resp{comResp, "value"}
    json.NewEncoder(os.Stdout).Encode(r)
}

You may shorten the code above by using anonymous struct and not creating a local variable (not necessarily more readable):

if env == "dev" {
    json.NewEncoder(os.Stdout).Encode(struct {
        Response
        Key string
    }{comResp, "value"})
} else {
    json.NewEncoder(os.Stdout).Encode(struct {
        Response
        Secret string
    }{comResp, "value"})
}

Use a variable:

var key = "secret"
if env == "dev" {
   key = "dev"
}

Use that variable when creating a map to serialize to JSON:

m := map[string]interface{}{key: "value"}
p, err := json.Marshal(m)
if err != nil {
   // handle error
}
// p contains the json value.

playground example

The answer to this question depends on your actual use case. Here are 3 ways to achieve what you ask:

  1. Use map[string]interface{} instead of struct
  2. Use different struct types (as in the example from the question)
  3. Use a single struct type that contains fields for both "dev" and "prod" environments, use "json:,omitempty" and populate only necessary fields before marshalling to JSON.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM