Golang基礎学習:StructとJson
前言
構造体は、複数の任意のタイプの命名変数を組み合わせた集約データ型であり、構造体によって多次元/態様の集約論理データを形成し、全体を形成することができ、これらの命名変数を構造体のメンバーと呼ぶ.
Struct
宣言:
構造体メンバー(変数名)は、jsonとの変換を容易にするために大文字で始まることをお勧めします.具体的には、後述の部分を見ることができます.
単純な使用
構造と比較
構造体ネスト
匿名構造体ネスト
JSON
Jsonは非常に一般的なデータ受信と送信のフォーマット基準であり、その論理構造はstructと非常に似ており、goはjsonデータの処理と変換操作をサポートするために標準ライブラリencoding/jsonを提供している.次にstructとjsonの間の変換を例に挙げます.
struct=>jsonシーケンス化
上記の例では、jsonシーケンス化時に小文字の先頭の構造体メンバーは無視されます.json処理時にメンバーを小文字または別名として表示する場合は、ラベルを表示して追加できます.
このとき出力されるメンバーactorは小文字であり,同様にラベルはここでも別名と書くことができる.注意:
json=>struct逆シーケンス化
ここではピットを踏むことに注意せず、data 2はシーケンス化前に
ここで用いるUnmarshalメソッドに適用するオブジェクトは、既に単一またはメモリに存在するjsonオブジェクトであり、ファイル(socket/http等)が読み取るbyteストリームjsonデータに関しては、別の逆シーケンス化方式jsonを用いることが好適である.Decoder()は、バイトストリームを一度にメモリに読み込むのではなく、これらのシーンに適用されます.
使用例
実行結果:
まとめ
Golang構造体には多くの特性があり,jsonと密接に結合しており,後日よく用いられ,熟練した把握が必要である.
構造体は、複数の任意のタイプの命名変数を組み合わせた集約データ型であり、構造体によって多次元/態様の集約論理データを形成し、全体を形成することができ、これらの命名変数を構造体のメンバーと呼ぶ.
Struct
宣言:
//
type Employee struct {
ID int
Name string
Address string
DoB string
Position string
Salary int
ManagerID int
}
構造体メンバー(変数名)は、jsonとの変換を容易にするために大文字で始まることをお勧めします.具体的には、後述の部分を見ることができます.
単純な使用
// , , , , :
var bob *Employee = new(Employee) // &{0 0 0}
var claier *Employee = &Employee{
} // &{0 0 0}
var alice Employee // {0 0 0}
fmt.Println(bob, claier, alice)
//
alice.Salary = 3000
fmt.Println(alice, alice.Salary) // {0 3000 0} 3000
//
position := &bob.Position
*position = "Senior"
fmt.Println(bob) // &{0 Senior 0 0}
c := &claier
(*c).Name = "claier"
fmt.Println(*c) // &{0 alice Senior 3000 0}
構造と比較
/*
:
struct ,
*/
func NewEmployee(id int, name string) *Employee {
return &Employee{
ID: id, Name: name}
}
david := NewEmployee(4, "david")
fmt.Println(*david) // {4 david 0 0}
/*
struct
*/
// struct , 。 ,map key , struct map key
fmt.Println(alice == *bob) // false
type url struct {
host string
port int
}
pageViews := make(map[url]int)
pageViews[url{
"www.baidu.com", 443}]++
構造体ネスト
/*
struct
struct , , :
: -> -> ->
*/
//
type School struct {
name string
}
type Grade struct {
level int
school School
}
type Classes struct {
grade Grade
id int
}
type Student struct {
name string
age int
classes Classes
}
var xiaoming Student
xiaoming.name = "xiaoming"
xiaoming.classes.grade.school.name = "NO.1 School"
xiaoming.classes.grade.level = 3
xiaoming.classes.id = 2
xiaoming.age = 8
fmt.Println(xiaoming) // {xiaoming 8 {
{3 {NO.1 School}} 2}}
匿名構造体ネスト
/*
:
, , 。 , ,
, , ( )。 ,xiaoli.name Student2.name,
xiaoli.classes.grade.school.name, xiaoli.School.name 。
, , 。
*/
type Grade2 struct {
level int
School
}
type Classes2 struct {
Grade2
id int
}
type Student2 struct {
name string
age int
Classes2
}
var xiaoli Student2
xiaoli.name = "xiaoli"
xiaoli.School.name = "NO.2 School" // xiaoli.classes.grade.school.name
xiaoli.level = 4 // xiaoli.classes.grade.level
xiaoli.id = 3 // xiaoli.classes.id
xiaoli.age = 9
fmt.Println(xiaoli) // {xiaoli 9 {
{4 {NO.2 School}} 3}}
//
xiaohong := Student2{
"xiaohong", 11, Classes2{
Grade2{
5, School{
"NO.2 School"}}, 4}}
//
xiaotian := Student2{
"xiaotian",
12,
Classes2{
Grade2{
6,
School{
"NO.2 School",
},
},
5,
},
}
fmt.Println(xiaohong) // {xiaohong 11 {
{5 {NO.2 School}} 4}}
fmt.Println(xiaotian) // {xiaotian 12 {
{6 {NO.2 School}} 5}}
JSON
Jsonは非常に一般的なデータ受信と送信のフォーマット基準であり、その論理構造はstructと非常に似ており、goはjsonデータの処理と変換操作をサポートするために標準ライブラリencoding/jsonを提供している.次にstructとjsonの間の変換を例に挙げます.
struct=>jsonシーケンス化
type Movie struct {
Name string
Year int
actor []string
}
var movies = []Movie{
{
Name: "movie1", Year: 1999, actor: []string{
"zhangsan", "lisi"}},
{
Name: "movie2", Year: 2000, actor: []string{
"wangwu", "zhaoliu"}},
}
data, err := json.Marshal(movies)
if err != nil {
fmt.Println("Json parse error")
return
}
fmt.Println(movies) // [{movie1 1999 [zhangsan lisi]} {movie2 2000 [wangwu zhaoliu]}]
fmt.Printf("%s
", data) // [{"Name":"movie1","Year":1999},{"Name":"movie2","Year":2000}]
// : actor , JSON struct , , 。
上記の例では、jsonシーケンス化時に小文字の先頭の構造体メンバーは無視されます.json処理時にメンバーを小文字または別名として表示する場合は、ラベルを表示して追加できます.
type Movie2 struct {
Name string
Year int
Actor []string `json:"actor"`
}
var movies2 = []Movie2{
{Name: "movie1", Year: 1999, Actor: []string{"zhangsan", "lisi"}},
{Name: "movie2", Year: 2000, Actor: []string{"wangwu", "zhaoliu"}},
}
data2, _ := json.Marshal(movies2)
fmt.Printf("%s
", data2) // [{"Name":"movie1","Year":1999,"actor":["zhangsan","lisi"]},{"Name":"movie2","Year":2000,"actor":["wangwu","zhaoliu"]}]
このとき出力されるメンバーactorは小文字であり,同様にラベルはここでも別名と書くことができる.注意:
json:"actor"
、コロンの間にスペースはありません.json=>struct逆シーケンス化
//
//var movies3 Movie2
// , . :
// Movie2 data2 json , :json: cannot unmarshal array into Go value of type main.Movie2
// : json , struct , , movies3 []Movie2 slice 。go , !
// , unmarshal , json.Decoder json , json_template.go 。
var movies3 []Movie2
err2 := json.Unmarshal(data2, &movies3)
if err2 != nil {
fmt.Println("Json parse error", err2)
}
fmt.Printf("%v
", movies3) // [{movie1 1999 [zhangsan lisi]} {movie2 2000 [wangwu zhaoliu]}]
fmt.Println(movies3[0].Year) // 1999
ここではピットを踏むことに注意せず、data 2はシーケンス化前に
[]Movie2
のslice構造であり、Movie 2 structタイプの変数ポインタを宣言してjson逆シーケンス化のデータを受信際に異常を投げ出す、ここでも[]Movie2
のsliceタイプ変数を同様に使用すべきである.ここで用いるUnmarshalメソッドに適用するオブジェクトは、既に単一またはメモリに存在するjsonオブジェクトであり、ファイル(socket/http等)が読み取るbyteストリームjsonデータに関しては、別の逆シーケンス化方式jsonを用いることが好適である.Decoder()は、バイトストリームを一度にメモリに読み込むのではなく、これらのシーンに適用されます.
使用例
package main
/*
Github issue api json go struct demo
*/
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
"strings"
"time"
)
const IssueURL = "https://api.github.com/search/issues"
type IssuesSearchResult struct {
TotalCount int `json:"total_count"`
Items []*Issue
}
type Issue struct {
Number int
HTMLURL string `json:"html_url"`
Title string
State string
User *User
CreateAt time.Time `json:"created_at"`
Body string
}
type User struct {
Login string
HTMLURL string `json:"html_url"`
}
func SearchIssues(terms []string) (*IssuesSearchResult, error) {
q := url.QueryEscape(strings.Join(terms, " ")) // slice
resp, err := http.Get(IssueURL + "?q=" + q)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
return nil, err
}
var result IssuesSearchResult
// json.NewDecoder().decode() , unmarshal ,unmarshal 。
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
resp.Body.Close()
return nil, err
}
resp.Body.Close()
return &result, nil
}
func main() {
res, err := SearchIssues(os.Args[1:]) // : go run ./json_template.go repo:golang/go is:open json decoder , url
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Items[0].Title)
fmt.Printf("%d issues:
", res.TotalCount)
for _, item := range res.Items {
fmt.Printf(
"IssueID: #%d\tTime: %s\tUser: %s\tTitle: %s
", item.Number, item.CreateAt, item.User.Login, item.Title)
}
}
実行結果:
encoding/json: second decode after error impossible
35 issues:
IssueID: #31701 Time: 2019-04-26 20:50:17 +0000 UTC User: lr1980 Title: encoding/json: second decode after error impossible
IssueID: #31789 Time: 2019-05-01 18:30:06 +0000 UTC User: mgritter Title: encoding/json: provide a way to limit recursion depth
IssueID: #29688 Time: 2019-01-11 17:07:05 +0000 UTC User: sheerun Title: proposal: encoding/json: add InputOffset to json decoder
IssueID: #29686 Time: 2019-01-11 16:38:04 +0000 UTC User: sheerun Title: json: Add InputOffset for stream byte offset access
IssueID: #28923 Time: 2018-11-22 13:50:18 +0000 UTC User: mvdan Title: encoding/json: speed up the decoding scanner
IssueID: #11046 Time: 2015-06-03 19:25:08 +0000 UTC User: kurin Title: encoding/json: Decoder internally buffers full input
IssueID: #29035 Time: 2018-11-30 11:21:31 +0000 UTC User: jaswdr Title: proposal: encoding/json: add error var to compare the returned error when using json.Decoder.DisallowUnknownFields()
IssueID: #30301 Time: 2019-02-18 19:49:27 +0000 UTC User: zelch Title: encoding/xml: option to treat unknown fields as an error
IssueID: #30701 Time: 2019-03-09 12:16:34 +0000 UTC User: LouAdrien Title: encoding/json: ignore tag "-" not working on embedded sub structure when decoding
IssueID: #12001 Time: 2015-08-03 19:14:17 +0000 UTC User: lukescott Title: encoding/json: Marshaler/Unmarshaler not stream friendly
IssueID: #16212 Time: 2016-06-29 16:07:36 +0000 UTC User: josharian Title: encoding/json: do all reflect work before decoding
IssueID: #28143 Time: 2018-10-11 07:08:25 +0000 UTC User: Carpetsmoker Title: proposal: encoding/json: add "readonly" tag
IssueID: #26946 Time: 2018-08-12 18:19:01 +0000 UTC User: deuill Title: encoding/json: clarify what happens when unmarshaling into a non-empty interface{
}
IssueID: #5901 Time: 2013-07-17 16:39:15 +0000 UTC User: rsc Title: encoding/json: allow override type marshaling
IssueID: #27179 Time: 2018-08-23 18:21:32 +0000 UTC User: lavalamp Title: encoding/json: no way to preserve the order of map keys
IssueID: #21823 Time: 2017-09-09 21:43:31 +0000 UTC User: 243083df Title: encoding/xml: very low performance in xml parser
IssueID: #22752 Time: 2017-11-15 23:46:13 +0000 UTC User: buyology Title: proposal: encoding/json: add access to the underlying data causing UnmarshalTypeError
IssueID: #14750 Time: 2016-03-10 13:04:44 +0000 UTC User: cyberphone Title: encoding/json: parser ignores the case of member names
IssueID: #20754 Time: 2017-06-22 14:19:31 +0000 UTC User: rsc Title: encoding/xml: unmarshal only processes first XML element
IssueID: #28189 Time: 2018-10-13 16:22:53 +0000 UTC User: adnsv Title: encoding/json: confusing errors when unmarshaling custom types
IssueID: #7213 Time: 2014-01-27 00:23:01 +0000 UTC User: davecheney Title: cmd/compile: escape analysis oddity
IssueID: #7872 Time: 2014-04-26 17:47:25 +0000 UTC User: extemporalgenome Title: encoding/json: Encoder internally buffers full output
IssueID: #20528 Time: 2017-05-30 11:45:14 +0000 UTC User: jvshahid Title: net/http: connection reuse does not work happily with normal use of json package
IssueID: #17609 Time: 2016-10-26 16:07:27 +0000 UTC User: nathanjsweet Title: encoding/json: ambiguous fields are marshalled
IssueID: #19636 Time: 2017-03-21 12:25:10 +0000 UTC User: josselin-c Title: encoding/base64: decoding is slow
IssueID: #22816 Time: 2017-11-20 13:12:06 +0000 UTC User: ganelon13 Title: encoding/json: include field name in unmarshal error messages when extracting time.Time
IssueID: #21092 Time: 2017-07-19 23:11:40 +0000 UTC User: trotha01 Title: encoding/json: unmarshal into slice reuses element data between len and cap
IssueID: #28941 Time: 2018-11-25 14:06:38 +0000 UTC User: mvdan Title: cmd/compile: teach prove about slice expressions
IssueID: #15808 Time: 2016-05-24 02:13:10 +0000 UTC User: randall77 Title: cmd/compile: loads/constants not lifted out of loop
IssueID: #28952 Time: 2018-11-26 09:59:26 +0000 UTC User: mvdan Title: cmd/compile: consider teaching prove about unexported integer fields
まとめ
Golang構造体には多くの特性があり,jsonと密接に結合しており,後日よく用いられ,熟練した把握が必要である.