首頁 > 軟體

Go語言中的Struct結構體

2022-07-16 18:00:53

一、Struct結構體

Go語言中沒有像C#、Java一樣的Class,只有Struct這樣的結構體。Go語言使用type關鍵字來定義一個型別。

如下:

type User struct {
   Name string
   Age int32
   Sex int16
   AvatarUrl string
}

二、Struct的宣告以及初始化

初始化方法一:直接定義,通過變數名.成員名的方式賦值

//初始化方法1
var user1 User
user1.Name = "BigOrange"
user1.Age = 20
user1.Sex = 1
user1.AvatarUrl = "xxxxxxx"
 
fmt.Println("User1:",user1)

初始化方法二:直接通過{}進行初始化,這點和C#不一樣,C#初始化的時候一般用new,例如 var user = new User{xxxxx,xxxxx,xxxx}

//初始化方法2
var user2 User = User{
   Name:"BigBanana",
   Age:23,
   Sex:0,
   AvatarUrl:"yyyyyyyyyyy",
}
 
fmt.Println("User2:",user2)
 
//初始化方法2簡化
 user3 := User{
   Name:"BigBanana",
   Age:23,
   Sex:0,
   AvatarUrl:"yyyyyyyyyyy",
}
 
fmt.Println("User3:",user3)

三、Struct的指標

Struct的指標比較簡單,就是通過&獲取地址,此外還可以用new來返回一個物件的指標

方式一

var user4 *User = &User{
    Name:"BigPeach",
    Age:22,
    Sex:1,
    AvatarUrl:"zzzzzzz",
 }
 
fmt.Println("User4:",user4)
fmt.Println("User4:",*user4)

方式二

user5 := new(User)
user5.Name="BigGrape"
user5.Age= 25
user5.Sex= 1
user5.AvatarUrl= "mmmmmmmmm"
fmt.Println("User5:",user5)
fmt.Println("User5:",*user5)

上面第二種方式可能會有些疑問,user5不是一個指標型別嗎?怎麼和上面的值型別一樣直接用【變數名.成員】 的方式進行賦值了呢? 不是應該 (*user5).Name 這樣嗎?沒有錯!

這是GO語言實現的一個語法糖,實際上GO語言會幫我轉換。

四、Struct成員的記憶體佈局以及實現建構函式

例如下面這樣的一段程式碼

package main
 
import "fmt"
 
type AddressDemo struct {
   addr1 int32
   addr2 int32
   addr3 int32
}
 
func main(){
   addr := new(AddressDemo)
   fmt.Println("add1地址:",&addr.addr1)
   fmt.Println("add2地址:",&addr.addr2)
   fmt.Println("add3地址:",&addr.addr3)
}

結果:

add1地址: 0xc042060080
add2地址: 0xc042060084
add3地址: 0xc042060088

可以看出來,addr1、addr2、addr3都是int32,都是佔用了4個位元組,他們的地址分配都是連續的。

For example: 下面這個User包,就實現了一個NewUser的方法,他就是建構函式

package User
 
type User struct {
   Name string
   Age int32
   Sex int16
   AvatarUrl string
}
 
func NewUser(name string , age int32,sex int16,avatarUrl string) *User{
   user:=new(User)
   user.Name = name
   user.Age = age
   user.Sex = sex
   user.AvatarUrl = avatarUrl
 
   return user
}

五、Struct中的匿名欄位和巢狀

可以像下面這樣宣告:後兩個欄位沒有名字

type Class struct {
   Name string
   int
   string
}

使用的時候,對於匿名的欄位,直接賦值就可以了

class1:=Class{
   Name:"Class1",
   int:123,
   string:"sssssss",
}
 
fmt.Println("class1:",class1)

結構體的巢狀

type User struct {
   Name string
   Age int32
   Sex int16
   AvatarUrl string
}
 
type Class struct {
   Name string
}
 
type Student struct {
   User User
   Class Class
}

使用:

func main() {
   stu:=new(User.Student)
    
   stu.Class = User.Class{
      Name:"5-2",
   }
    
   stu.User = User.User {
       Name:"BigBanana",
      Sex:1,
      Age:12,
      AvatarUrl:"asdasdasd",
   }
    
   fmt.Println(stu)
}

如果是匿名結構體巢狀呢?修改一下Student

type Student struct {
   User User
   Class
}

使用在對Class這個成員進行賦值的時候,可以發現,既可以使用

stu.Class = User.Class{
   Name:"5-2",
}

也可以使用Name直接賦值,順序就是現在當前的結構體找,找不到再從匿名結構體中查詢,正好找到Class裡面有Name

stu.Name = "5-2"

如果Class和User都是匿名結構巢狀,但是他們裡面都有Name,當我們使用stu.Name的時候,那他存取的是Class裡的Name還是User裡面的Name? 那麼豈不是衝突了? 如何處理衝突?

當我試圖給stu.Name賦值的時候,編譯器報錯了,內容如下,也就是它找不到應該給誰賦值。

這時候要解決這個衝突,必須指定是哪個匿名欄位裡面的Name

stu:=new(User.Student)
 
stu.User.Name = "123123"
stu.Class.Name = "5-2"
 
stu.User = User.User {
   Name:"BigBanana",
   Sex:1,
   Age:12,
   AvatarUrl:"asdasdasd",
}

六、結構體內欄位的可見性

和包一樣,小寫的欄位外部不可見,大寫的外部可見

七、結構體的Tag

tag是結構體的元資訊,可以在執行的時候通過反射的機制讀出來。

怎麼寫tag?

以`作為開頭和結尾,中間是key-value形式的字串,每一個鍵值對以,作為分隔。例如

type User struct {
   UserName string   `json:"userName",db:"User_Name"`
   Age int32         `json:"age"`
   Sex int16         `json:"sex"`
   AvatarUrl string  `json:"avatarUrl",db:"Avatar_Url"`
}

使用並執行:

func main() {

   user := User.User {
      UserName:"BigBanana",
      Sex:1,
      Age:12,
      AvatarUrl:"asdasdasd",
   }

   fmt.Println(user)

   data,_:=json.Marshal(user)

   fmt.Println(string(data))
   
}

結果:

{"userName":"BigBanana","age":12,"sex":1,"avatarUrl":"asdasdasd"}

可以看到,如果打了這個tag,會顯示tag後面的標記名稱。

此外:如果欄位名稱是小寫,那麼json輸出的時候就不會有這個欄位被列印了。

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對it145.com的支援。如果你想了解更多相關內容請檢視下面相關連結


IT145.com E-mail:sddin#qq.com