Why Golang cannot generate json from struct with front lowercase character? - go

I am trying to print json result from struct I created as following:
type Machine struct {
m_ip string
m_type string
m_serial string
}
and print out
m:= &Machine{ m_ip:"test", m_type:"test", m_serial:"test" }
m_json:= json.Marshal(m)
fmt.Println(m_json)
However, result returned just {}
Secondly,I tried to changed the first letter of words to Uppercase as follow:
type Machine struct{
MachIp string
MachType string
MachSerial string
}
and it works! Why doesn't the word with lowercase character at the front work, anyway?

Go uses case to determine whether a particular identifier is public or private within the context of your package. In your first example, the fields are not visible to json.Marshal because it is not part of the package containing your code. When you changed the fields to be upper case, they became public so could be exported.
If you need to use lower case identifiers in your JSON output though, you can tag the fields with the desired identifiers. For example:
type Machine struct{
MachIp string `json:"m_ip"`
MachType string `json:"m_type"`
MachSerial string `json:"m_serial"`
}

Related

How to use mapstructure tag as json tag?

I'm introducing a package from a third party that has this struct with mapstructure tag.
I want the instance of this struct to be json with mapstructure specified value.What should I do?
I can add json tag, but in doing so,I modify package files,I think this is a bad way.
type ServiceConfig struct {
// name of the service
Name string `mapstructure:"name"`
// set of endpoint definitions
Endpoints string `mapstructure:"end_points"`
// defafult timeout
Timeout time.Duration `mapstructure:"timeout"`
}
I want to get:
{"name":"sss", "end_points" :"xxx", "timeout" : "120"}
If you do not want to modify the package files, you can create another struct with the same field names, but with JSON tags, and copy:
type JSONServiceConfig struct {
Name string `json:"name"`
Endpoints string `json:"end_points"`
Timeout time.Duration `json:"timeout"`
}
Then:
x := JSONServiceConfig(serviceConfig)
You cannot do what you want without modifying the mapstructure source, and it would probably get a little bit hairy if you want to specify options, such as json's omitempty. However, you can simply add a second struct tag for this
type ServiceConfig struct {
// name of the service
Name string `mapstructure:"name" json:"name"`
// set of endpoint definitions
Endpoints string `mapstructure:"end_points" json:"end_points"`
// defafult timeout
Timeout time.Duration `mapstructure:"timeout" json:"timeout"`
}
From the documentation of reflect
By convention, tag strings are a concatenation of optionally
space-separated key:"value" pairs. Each key is a non-empty string
consisting of non-control characters other than space (U+0020 ' '),
quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using
U+0022 '"' characters and Go string literal syntax.
Here's a simple example on the playground

How to access specific fields from structs in Golang

Suppose I have the following code:
type User struct {
ID string
Username string
Name string
Password string
}
What I want to do is create another struct that can access certain fields from the User struct, instead of accessing all of it, to prevent people from seeing the password, for example.
This does not work:
type Note struct {
ID string
Text string
UserID User.ID
}
Is there any way to do this, or do I simply create the Note.UserID field to have the same data type as the ID in the User struct?
Assuming the types are in different packages you can do this by exporting vs not exporting the fields. A field who's name begins with a lower case letter is not exported, meaning it is not visible outside the package where it is declared/defined. So, in this case if the user existed in one package, call it user while the other type were declared in another you could accomplish this 'hiding' of properties by changing the definition to;
type User struct {
ID string
username string
name string
password string
}
If the two types live in the same package there is no way of making a field private/hidden/ect, everything will be available in that scope.
The Go Programming Language Specification
Exported identifiers
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case
letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name
or method name.
All other identifiers are not exported.
Give User its own package and don't export the password.
For example,
package user
type User struct {
ID string
Username string
Name string
password string
}
func (u *User) IsPassword(password string) bool {
return password == u.password
}

What is the usage of backtick in golang structs definition? [duplicate]

This question already has an answer here:
Strange type definition syntax in Golang (name, then type, then string literal)
(1 answer)
Closed 7 years ago.
type NetworkInterface struct {
Gateway string `json:"gateway"`
IPAddress string `json:"ip"`
IPPrefixLen int `json:"ip_prefix_len"`
MacAddress string `json:"mac"`
...
}
I'm quite confused what's the function of contents in backtick, like json:"gateway".
Is it just comment, like //this is the gateway?
The content inside the backticks are tags:
A field declaration may be followed by an optional string literal tag,
which becomes an attribute for all the fields in the corresponding
field declaration. The tags are made visible through a reflection
interface and take part in type identity for structs but are otherwise
ignored.
// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}
See this question and answer for a more detailed explanation and answer.
The back quotes are used to create raw string literals which can contain any type of character:
Raw string literals are character sequences between back quotes ``.
Within the quotes, any character is legal except back quote.
You can add extra meta information to Go structs in the form of tags. Here are some examples of use cases.
In this case, the json:"gateway" is used by the json package to encode the value of Gateway into the key gateway in the corresponding json object.
Example:
n := NetworkInterface{
Gateway : "foo"
}
json.Marshal(n)
// will output `{"gateway":"foo",...}`

Properly distinguish between not set (nil) and blank/empty value

Whats the correct way in go to distinguish between when a value in a struct was never set, or is just empty, for example, given the following:
type Organisation struct {
Category string
Code string
Name string
}
I need to know (for example) if the category was never set, or was saved as blank by the user, should I be doing this:
type Organisation struct {
Category *string
Code *string
Name *string
}
I also need to ensure I correctly persist either null or an empty string to the database
I'm still learning GO so it is entirely possible my question needs more info.
The zero value for a string is an empty string, and you can't distinguish between the two.
If you are using the database/sql package, and need to distinguish between NULL and empty strings, consider using the sql.NullString type. It is a simple struct that keeps track of the NULL state:
type NullString struct {
String string
Valid bool // Valid is true if String is not NULL
}
You can scan into this type and use it as a query parameter, and the package will handle the NULL state for you.
Google's protocol buffers (https://code.google.com/p/goprotobuf/) use pointers to describe optional fields.
The generated objects provide GetFoo methods which take the pain away from testing for nil (a.GetFoo() returns an empty string if a.Foo is nil, otherwise it returns *a.Foo).
It introduces a nuisance when you want to write literal structs (in tests, for example), because &"something" is not valid syntax to generate a pointer to a string, so you need a helper function (see, for example, the source code of the protocol buffer library for proto.String).
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
return &v
}
Overall, using pointers to represent optional fields is not without drawbacks, but it's certainly a viable design choice.
The standard database/sql package provides a NullString struct (members are just String string and Valid bool). To take care of some of the repetitive work of persistence, you could look at an object-relational manager like gorp.
I looked into whether there was some way to distinguish two kinds of empty string just out of curiosity, and couldn't find one. With []bytes, []byte{} == []byte(nil) currently returns false, but I'm not sure if the spec guarantees that to always remain true. In any case, it seems like the most practical thing to do is to go with the flow and use NullString.

What are the use(s) for struct tags in Go?

In the Go Language Specification, it mentions a brief overview of tags:
A field declaration may be followed by an optional string literal tag,
which becomes an attribute for all the fields in the corresponding
field declaration. The tags are made visible through a reflection
interface but are otherwise ignored.
// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}
This is a very short explanation IMO, and I was wondering if anyone could provide me with what use these tags would be?
A tag for a field allows you to attach meta-information to the field which can be acquired using reflection. Usually it is used to provide transformation info on how a struct field is encoded to or decoded from another format (or stored/retrieved from a database), but you can use it to store whatever meta-info you want to, either intended for another package or for your own use.
As mentioned in the documentation of reflect.StructTag, by convention the value of a tag string is a space-separated list of key:"value" pairs, for example:
type User struct {
Name string `json:"name" xml:"name"`
}
The key usually denotes the package that the subsequent "value" is for, for example json keys are processed/used by the encoding/json package.
If multiple information is to be passed in the "value", usually it is specified by separating it with a comma (','), e.g.
Name string `json:"name,omitempty" xml:"name"`
Usually a dash value ('-') for the "value" means to exclude the field from the process (e.g. in case of json it means not to marshal or unmarshal that field).
Example of accessing your custom tags using reflection
We can use reflection (reflect package) to access the tag values of struct fields. Basically we need to acquire the Type of our struct, and then we can query fields e.g. with Type.Field(i int) or Type.FieldByName(name string). These methods return a value of StructField which describes / represents a struct field; and StructField.Tag is a value of type StructTag which describes / represents a tag value.
Previously we talked about "convention". This convention means that if you follow it, you may use the StructTag.Get(key string) method which parses the value of a tag and returns you the "value" of the key you specify. The convention is implemented / built into this Get() method. If you don't follow the convention, Get() will not be able to parse key:"value" pairs and find what you're looking for. That's also not a problem, but then you need to implement your own parsing logic.
Also there is StructTag.Lookup() (was added in Go 1.7) which is "like Get() but distinguishes the tag not containing the given key from the tag associating an empty string with the given key".
So let's see a simple example:
type User struct {
Name string `mytag:"MyName"`
Email string `mytag:"MyEmail"`
}
u := User{"Bob", "bob#mycompany.com"}
t := reflect.TypeOf(u)
for _, fieldName := range []string{"Name", "Email"} {
field, found := t.FieldByName(fieldName)
if !found {
continue
}
fmt.Printf("\nField: User.%s\n", fieldName)
fmt.Printf("\tWhole tag value : %q\n", field.Tag)
fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag"))
}
Output (try it on the Go Playground):
Field: User.Name
Whole tag value : "mytag:\"MyName\""
Value of 'mytag': "MyName"
Field: User.Email
Whole tag value : "mytag:\"MyEmail\""
Value of 'mytag': "MyEmail"
GopherCon 2015 had a presentation about struct tags called:
The Many Faces of Struct Tags (slide) (and a video)
Here is a list of commonly used tag keys:
json      - used by the encoding/json package, detailed at json.Marshal()
xml       - used by the encoding/xml package, detailed at xml.Marshal()
bson      - used by gobson, detailed at bson.Marshal(); also by the mongo-go driver, detailed at bson package doc
protobuf  - used by github.com/golang/protobuf/proto, detailed in the package doc
yaml      - used by the gopkg.in/yaml.v2 package, detailed at yaml.Marshal()
db        - used by the github.com/jmoiron/sqlx package; also used by github.com/go-gorp/gorp package
orm       - used by the github.com/astaxie/beego/orm package, detailed at Models – Beego ORM
gorm      - used by gorm.io/gorm, examples can be found in their docs
valid     - used by the github.com/asaskevich/govalidator package, examples can be found in the project page
datastore - used by appengine/datastore (Google App Engine platform, Datastore service), detailed at Properties
schema    - used by github.com/gorilla/schema to fill a struct with HTML form values, detailed in the package doc
asn       - used by the encoding/asn1 package, detailed at asn1.Marshal() and asn1.Unmarshal()
csv       - used by the github.com/gocarina/gocsv package
env - used by the github.com/caarlos0/env package
Here is a really simple example of tags being used with the encoding/json package to control how fields are interpreted during encoding and decoding:
Try live: http://play.golang.org/p/BMeR8p1cKf
package main
import (
"fmt"
"encoding/json"
)
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName string `json:"middle_name,omitempty"`
}
func main() {
json_string := `
{
"first_name": "John",
"last_name": "Smith"
}`
person := new(Person)
json.Unmarshal([]byte(json_string), person)
fmt.Println(person)
new_json, _ := json.Marshal(person)
fmt.Printf("%s\n", new_json)
}
// *Output*
// &{John Smith }
// {"first_name":"John","last_name":"Smith"}
The json package can look at the tags for the field and be told how to map json <=> struct field, and also extra options like whether it should ignore empty fields when serializing back to json.
Basically, any package can use reflection on the fields to look at tag values and act on those values. There is a little more info about them in the reflect package
http://golang.org/pkg/reflect/#StructTag :
By convention, tag strings are a concatenation of optionally
space-separated key:"value" pairs. Each key is a non-empty string
consisting of non-control characters other than space (U+0020 ' '),
quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using
U+0022 '"' characters and Go string literal syntax.
It's some sort of specifications that specifies how packages treat with a field that is tagged.
for example:
type User struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
json tag informs json package that marshalled output of following user
u := User{
FirstName: "some first name",
LastName: "some last name",
}
would be like this:
{"first_name":"some first name","last_name":"some last name"}
other example is gorm package tags declares how database migrations must be done:
type User struct {
gorm.Model
Name string
Age sql.NullInt64
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // set field size to 255
MemberNumber *string `gorm:"unique;not null"` // set member number to unique and not null
Num int `gorm:"AUTO_INCREMENT"` // set num to auto incrementable
Address string `gorm:"index:addr"` // create index with name `addr` for address
IgnoreMe int `gorm:"-"` // ignore this field
}
In this example for the field Email with gorm tag we declare that corresponding column in database for the field email must be of type varchar and 100 maximum length and it also must have unique index.
other example is binding tags that are used very mostly in gin package.
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
the binding tag in this example gives hint to gin package that the data sent to API must have user and password fields cause these fields are tagged as required.
So generraly tags are data that packages require to know how should they treat with data of type different structs and best way to get familiar with the tags a package needs is READING A PACKAGE DOCUMENTATION COMPLETELY.

Resources