溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go?Struct結(jié)構(gòu)體如何實現(xiàn)

發(fā)布時間:2023-03-15 11:36:58 來源:億速云 閱讀:121 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細介紹“Go Struct結(jié)構(gòu)體如何實現(xiàn)”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“Go Struct結(jié)構(gòu)體如何實現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

什么是結(jié)構(gòu)體

Go語言中沒有“類”的概念,也不支持“類”的繼承等面向?qū)ο蟮母拍?。(繼承,多態(tài),封裝)

Go語言中通過結(jié)構(gòu)體的內(nèi)嵌再配合接口比面向?qū)ο缶哂懈叩臄U展性和靈活性。

1. 基本實例化(方法1)

只有當結(jié)構(gòu)體實例化時,才會真正地分配內(nèi)存(其實也就是使用new),也就是必須實例化后才能使用結(jié)構(gòu)體的字段。

結(jié)構(gòu)體本身也是一種類型,我們可以像聲明內(nèi)置類型一樣使用 var 關鍵字聲明結(jié)構(gòu)體類型。

type person struct { 
name string 
city string 
age int 
}
 
func main() { 
var p1 person 
p1.name = "張三" 
p1.city = "北京" 
p1.age = 18
fmt.Printf("p1=%v\n", p1) // p1={張三 北京 18}
fmt.Printf("p1=%#v\n", p1) // p1=main.person{name:"張三", city:"北京", age:18} }

2. new實例化(方法2)

我們還可以通過使用 new 關鍵字對結(jié)構(gòu)體進行實例化,得到的是結(jié)構(gòu)體的地址

從打印的結(jié)果中我們可以看出 p2 是一個結(jié)構(gòu)體指針。

注意:在 Golang 中支持對結(jié)構(gòu)體指針直接使用.來訪問結(jié)構(gòu)體的成員。

p2.name = "張三" 其實在底層是 (*p2).name = "張三"

type person struct {
name string
city string
age int
}
 
func main() {
    var p2 = new(person)
    p2.name = "張三"
    p2.age = 20
    p2.city = "北京"
    fmt.Printf("p2=%#v \n", p2) //p2=&main.person{name:"張三", city:"北京", age:20}
}

3. 鍵值對初始化(方法3 結(jié)構(gòu)體能夠使用指針就使用指針)

type person struct {
name string
city string
age int
}
 
func main() {
    p4 := &person{
    name: "zhangsan",
    city: "北京",
    age: 18,
    }
    // p4=&main.person{name:"zhangsan", city:"北京", age:18}
    fmt.Printf("p4=%#v\n", p4)
}

結(jié)構(gòu)體方法和接收者

1. 結(jié)構(gòu)體說明

在 go 語言中,沒有類的概念但是可以給類型(結(jié)構(gòu)體,自定義類型)定義方法。所謂方法就是定義了接收者的函數(shù)。

Go語言中的方法(Method)是一種作用于特定類型變量的函數(shù)。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于其他語言中的this或者 self。

方法的定義格式如下:

func (接收者變量 接收者類型) 方法名(參數(shù)列表) (返回值) {
函數(shù)體
}

2. 結(jié)構(gòu)體方法和接收者

給結(jié)構(gòu)體 Person 定義一個方法打印 Person 的信息

type Person struct {
    name string
    age int8
}
 
func (p Person) printInfo() {
    fmt.Printf("姓名:%v 年齡:%v", p.name, p.age) // 姓名:小王子 年齡:25
}
 
func main() {
    p1 := Person{
        name: "小王子",
        age: 25,
    }
    p1.printInfo() // 姓名:小王子 年齡:25
}

3. 值類型和指針類型接收者

實例1:給結(jié)構(gòu)體 Person 定義一個方法打印 Person 的信息

值類型的接收者

  • 當方法作用于值類型接收者時,Go 語言會在代碼運行時將接收者的值復制一份。

  • 在值類型接收者的方法中可以獲取接收者的成員值,但 修改操作只是針對副本 ,無法修改接收者變量本身。

指針類型的接收者

  • 指針類型的接收者由一個結(jié)構(gòu)體的指針組成

  • 由于指針的特性,調(diào)用方法時修改接收者指針的任意成員變量,在方法結(jié)束后,修改都是有效的。

  • 這種方式就十分接近于其他語言中面向?qū)ο笾械?this 或者 self

方法大部分時候是自己處理自己的數(shù)據(jù),總結(jié)如下:

Go?Struct結(jié)構(gòu)體如何實現(xiàn)

encoding-json包

1. struct與json

比如我們 Golang 要給 App 或者小程序提供 Api 接口數(shù)據(jù),這個時候就需要涉及到結(jié)構(gòu)體和Json 之間的相互轉(zhuǎn)換。

  • GolangJSON 序列化是指把結(jié)構(gòu)體數(shù)據(jù)轉(zhuǎn)化成 JSON 格式的字符串

  • Golang JSON 的反序列化是指把 JSON 數(shù)據(jù)轉(zhuǎn)化成 Golang 中的結(jié)構(gòu)體對象

  • Golang 中 的 序 列 化 和 反 序 列 化 主 要 通 過 "encoding/json" 包 中 的 json.Marshal() 和json.Unmarshal()方法實現(xiàn)

struct轉(zhuǎn)Json字符串

type Student struct {
ID int
Gender string
name string //私有屬性不能被 json 包訪問
Sno string
}
 
func main() {
 
var s1 = Student{
    ID: 1,
    Gender: "男",
    name: "李四",
    Sno: "s0001",
}
 
fmt.Printf("%#v\n", s1) // main.Student{ID:1, Gender:"男", name:"李
四",Sno:"s0001"}
var s, _ = json.Marshal(s1)
jsonStr := string(s)
fmt.Println(jsonStr) // {"ID":1,"Gender":"男","Sno":"s0001"}
}

Json字符串轉(zhuǎn)struct

type Student struct {
ID int
Gender string
Name string
Sno string
}
 
func main() {
    var jsonStr = `{"ID":1,"Gender":"男","Name":"李四","Sno":"s0001"}`
    var student Student //定義一個 Monster 實例
    err := json.Unmarshal([]byte(jsonStr), &student)
    if err != nil {
    fmt.Printf("unmarshal err=%v\n", err)
}
 
// 反序列化后 student=main.Student{ID:1, Gender:"男", Name:"李四", Sno:"s0001"}
student.Name="張三"
fmt.Printf("反序列化后 student=%#v student.Name=%v \n", student, student.Name)
}

2. struct tag

1)Tag標簽說明

  • Tag 是結(jié)構(gòu)體的元信息,可以在運行的時候通過反射的機制讀取出來。

  • Tag 在結(jié)構(gòu)體字段的后方定義,由一對反引號包裹起來

具體的格式如下:

key1:"value1" key2:"value2"

  • 結(jié)構(gòu)體 tag 由一個或多個鍵值對組成。鍵與值使用冒號分隔,值用雙引號括起來。

  • 同一個結(jié)構(gòu)體字段可以設置多個鍵值對 tag,不同的鍵值對之間使用空格分隔。

注意事項:

為結(jié)構(gòu)體編寫 Tag 時,必須嚴格遵守鍵值對的規(guī)則。

結(jié)構(gòu)體標簽的解析代碼的容錯能力很差,一旦格式寫錯,編譯和運行時都不會提示任何錯誤,通過反射也無法正確取值。例如不要在 key 和 value 之間添加空格。

Tag結(jié)構(gòu)體轉(zhuǎn)化Json字符串

type Student struct {
ID int `json:"id"` //通過指定 tag 實現(xiàn) json 序列化該字段時的 key(表示在做json操作的時候,用json指定的字段名)
Gender string `json:"gender"`
Name string
Sno string
}
 
func main() {
    var s1 = Student{
    ID: 1,
    Gender: "男",
    Name: "李四",
    Sno: "s0001",
}
 
// main.Student{ID:1, Gender:"男", Name:"李四", Sno:"s0001"}
fmt.Printf("%#v\n", s1)
var s, _ = json.Marshal(s1)
jsonStr := string(s)
fmt.Println(jsonStr) // {"id":1,"gender":"男","Name":"李四","Sno":"s0001"}
}

Json字符串轉(zhuǎn)成Tag結(jié)構(gòu)體

type Student struct {
    ID int `json:"id"` //通過指定 tag 實現(xiàn) json 序列化該字段時的 key
    Gender string `json:"gender"`
    Name string
    Sno string
}
 
func main() {
    var s2 Student
    var str = `{"id":1,"gender":"男","Name":"李四","Sno":"s0001"}`
    err := json.Unmarshal([]byte(str), &s2)
    if err != nil {
    fmt.Println(err)
    }
    // main.Student{ID:1, Gender:"男", Name:"李四", Sno:"s0001"}
    fmt.Printf("%#v", s2)
}

讀到這里,這篇“Go Struct結(jié)構(gòu)體如何實現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內(nèi)容的文章,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI