struct

面向?qū)ο缶幊?/h2>
  • Go支持面向?qū)ο缶幊烫匦?,但和傳統(tǒng)面向?qū)ο缶幊淌怯袇^(qū)別的,Go并不是純粹的面向?qū)ο笳Z(yǔ)言。
  • Go沒(méi)有類(lèi),其結(jié)構(gòu)體和其它編程語(yǔ)言中的類(lèi)具有同等的地位,可理解Go是基于結(jié)構(gòu)體來(lái)實(shí)現(xiàn)面向?qū)ο筇匦缘摹?/li>
  • Go面向?qū)ο缶幊谭浅:?jiǎn)介,去掉了傳統(tǒng)面向?qū)ο笳Z(yǔ)言的繼承、方法重載、構(gòu)造函數(shù)、析構(gòu)函數(shù)、隱藏的this指針等。
  • Go仍然具有面向?qū)ο缶幊痰睦^承、封裝、多態(tài)的特性,只是實(shí)現(xiàn)方式和傳統(tǒng)面向?qū)ο笳Z(yǔ)言不同。
  • Go面向?qū)ο蠛軆?yōu)雅,面向?qū)ο蟊旧砭褪钦Z(yǔ)言類(lèi)型系統(tǒng)的一部分,通過(guò)接口關(guān)聯(lián),耦合性低,也非常靈活。
  • Go中面向接口編程是非常重要的特性

結(jié)構(gòu)體與結(jié)構(gòu)體變量

  • 結(jié)構(gòu)體:自定義的數(shù)據(jù)類(lèi)型,表示一類(lèi)事物。
type struct_name struct {
  field1 datatype
  field2 datatype
}

//定義結(jié)構(gòu)體
type User struct {
    Id     int
    Name   string
    Birth  string
    Gender int
}
  • 結(jié)構(gòu)體變量:又稱(chēng)為實(shí)例或?qū)ο?,是具體的、實(shí)際的,代表一個(gè)具體變量。

//結(jié)構(gòu)體變量
var u User
u.Id = 1
u.Name = "alice"
u.Birth = "2020-12-21"
u.Gender = 1

結(jié)構(gòu)體字段

  • 結(jié)構(gòu)體字段又稱(chēng)為屬性,字段是結(jié)構(gòu)體組成部分,一般是基礎(chǔ)數(shù)據(jù)類(lèi)型、數(shù)組,也可以是引用類(lèi)型。
  • 字段聲明語(yǔ)法同變量一樣采用字段名 字段類(lèi)型
  • 字段類(lèi)型可分為:基本類(lèi)型、數(shù)組、引用類(lèi)型
  • 創(chuàng)建結(jié)構(gòu)體變量后若沒(méi)有給字段賦值,都會(huì)對(duì)應(yīng)一個(gè)零值作為默認(rèn)值。
  • 不同結(jié)構(gòu)體變量的字段是獨(dú)立互不影響,一個(gè)結(jié)構(gòu)體變量的更改不會(huì)影響到另外一個(gè),因?yàn)榻Y(jié)構(gòu)體是值類(lèi)型默認(rèn)是值拷貝。
字段類(lèi)型 類(lèi)型 零值
布爾類(lèi)型 基礎(chǔ) false
整型 基礎(chǔ) 0
字符串 基礎(chǔ) ""
數(shù)組類(lèi)型 基礎(chǔ) 默認(rèn)值與元素類(lèi)型相關(guān)
指針ptr/切片slice/映射map 引用 nil,未分配空間。

結(jié)構(gòu)體字段類(lèi)型若存在指針、slice、map,它們的零值都是nil,即還沒(méi)有分配空間,如果需要使用必須先make()。

類(lèi)型 創(chuàng)建
指針 new()
切片 make()
映射 make()
//定義結(jié)構(gòu)體
type User struct {
    Id    int
    array [5]float64
    slice []int
    ptr   *int
    dict  map[string]string
}

//結(jié)構(gòu)體變量
var u User
fmt.Printf("%+v\n", u)             // {Id:0 array:[0 0 0 0 0] slice:[] ptr:<nil> dict:map[]}
fmt.Printf("%t\n", u.slice == nil) //true
fmt.Printf("%t\n", u.ptr == nil)   //true
fmt.Printf("%t\n", u.dict == nil)  //true

創(chuàng)建結(jié)構(gòu)體變量

//創(chuàng)建結(jié)構(gòu)體變量
var u1 User             //直接聲明
fmt.Printf("%+v\n", u1) //{Id:0}

var u2 User = User{}
fmt.Printf("%+v\n", u2) //{Id:0}

采用結(jié)構(gòu)體指針?lè)绞絼?chuàng)建后,結(jié)構(gòu)體指針訪(fǎng)問(wèn)字段的標(biāo)準(zhǔn)方式應(yīng)該是 (*結(jié)構(gòu)體指針).字段名,但Go做了簡(jiǎn)化也支持結(jié)構(gòu)體指針.字段名,因?yàn)檫@種方式更加符合程序員的使用習(xí)慣。Go編譯器底層會(huì)對(duì)簡(jiǎn)化方式做自動(dòng)轉(zhuǎn)換。

var u3 *User = new(User)
fmt.Printf("%+v\n", u3) //&{Id:0}

var u4 *User = &User{}
fmt.Printf("%+v\n", u4) //&{Id:0}

簡(jiǎn)化寫(xiě)法

var u *User = new(User)
fmt.Printf("%+v\n", u) //&{Id:0}

(*u).Id = 100
fmt.Printf("%+v\n", *u)

u.Id = 200
fmt.Println(u)

由于u是一個(gè)指針,因此標(biāo)準(zhǔn)的給字段賦值的方式應(yīng)該采用的是(*u).Id = 100,但也可以直接采用u.Id = 200。由于Go設(shè)計(jì)者為了程序員使用方便,底層會(huì)對(duì)u.Id = 200添加取值運(yùn)算。

創(chuàng)建結(jié)構(gòu)體實(shí)例時(shí)可直接指定字段的值

type User struct {
    Id   int
    Name string
}

func main() {
    u := User{1, "alice"}
    fmt.Printf("%+v\n", u) // {Id:1 Name:alice}
}

內(nèi)存分配機(jī)制

例如:結(jié)構(gòu)體是值類(lèi)型,默認(rèn)賦值會(huì)拷貝副本,若需采用引用類(lèi)型方式,則需使用結(jié)構(gòu)體變量指針賦值。

u1 := User{1}
u2 := &u1 // var u2 *User = &u1
u2.Id = 100
fmt.Printf("%+v\n", u1)               // {Id:100}
fmt.Printf("%+v\n", u2)               // &{Id:100}
fmt.Printf("u1=%p, u2=%p\n", &u1, u2) // u1=0xc0000aa058, u2=0xc0000aa058

.點(diǎn)運(yùn)算符優(yōu)先級(jí)要高于*星號(hào)運(yùn)算符,下列為錯(cuò)誤寫(xiě)法:

u1 := User{1}
u2 := &u1 // var u2 *User = &u1
u2.Id = 100
fmt.Printf("%+v\n", *u2.Id) // invalid indirect of u2.Id (type int) (exit status 2)

注意事項(xiàng)

結(jié)構(gòu)體字段在內(nèi)存中是連續(xù)分布的

type Point struct {
    x, y int
}
type Rect struct {
    leftUp, rightDown Point
}

func main() {
    r := Rect{
        Point{0, 0},
        Point{4, 4},
    }
    fmt.Printf("%p\n", &r.leftUp.x)    // 0xc0000a8080
    fmt.Printf("%p\n", &r.leftUp.y)    // 0xc0000a8088
    fmt.Printf("%p\n", &r.rightDown.x) // 0xc0000a8090
    fmt.Printf("%p\n", &r.rightDown.y) // 0xc0000a8098
}

指針本身的地址是連續(xù)但指向的地址不一定是連續(xù)的

type Point struct {
    x, y int
}
type Rect struct {
    leftUp, rightDown *Point
}

func main() {
    r := Rect{
        &Point{0, 0},
        &Point{4, 4},
    }
    fmt.Printf("%p\n", &r.leftUp)    // 0xc000088220
    fmt.Printf("%p\n", &r.rightDown) // 0xc000088228

    fmt.Printf("%p\n", r.leftUp)    // 0xc0000aa070
    fmt.Printf("%p\n", r.rightDown) // 0xc0000aa080

}

結(jié)構(gòu)體是用戶(hù)單獨(dú)定義的類(lèi)型,和其它類(lèi)型進(jìn)行轉(zhuǎn)換時(shí)需具有完全相同的字段(名字、個(gè)數(shù)、類(lèi)型)。

type Point struct {
    x, y int
}
type Axis struct {
    x, y int
}

func main() {
    p1 := Point{0, 0}
    p2 := Axis(p1)
    fmt.Printf("%+v\n", p1) // {x:0 y:0}
    fmt.Printf("%+v\n", p2) // {x:0 y:0}
}

結(jié)構(gòu)體進(jìn)行type重新定義時(shí)相當(dāng)于取別名,Go會(huì)認(rèn)為是新的數(shù)據(jù)類(lèi)型,但相互之間可以強(qiáng)轉(zhuǎn)。

type Point struct {
    x, y int
}
type Axis Point

func main() {
    var p1 Point
    var p2 Axis

    //p1 = p2 //  cannot use p2 (type Axis) as type Point in assignment (exit status 2)

    p1 = Point(p2)
    fmt.Printf("%+v %+v\n", p1, p2) // {x:0 y:0} {x:0 y:0}
}

結(jié)構(gòu)體字段上可添加一個(gè)標(biāo)簽tag,標(biāo)簽可通過(guò)反射機(jī)制獲取,比如序列化和反序列化中。

type Response struct {
    Code int         `json:"code"`
    Msg  string      `json:"msg`
    Data interface{} `json:"data"`
}

func main() {
    response := Response{200, "success", nil}
    buf, err := json.Marshal(response)
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Printf("%s\n", buf) // {"code":200,"Msg":"success","data":null}
}

工廠(chǎng)模式

Go的結(jié)構(gòu)體沒(méi)有構(gòu)造函數(shù),可通過(guò)工廠(chǎng)模式來(lái)實(shí)例化結(jié)構(gòu)體。

// 結(jié)構(gòu)體
type user struct {
    Id   int
    Name string
}

// 工廠(chǎng)模式
func User(id int, name string) *user {
    return &user{
        Id:   id,
        Name: name,
    }
}

func main() {
    u := User(1, "alice")
    fmt.Printf("%+v\n", u) // &{Id:1 Name:alice}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 先介紹一下go語(yǔ)言的類(lèi)型系統(tǒng) Golang中的類(lèi)型系統(tǒng) 類(lèi)型系統(tǒng)是指一個(gè)語(yǔ)言的類(lèi)型體系結(jié)構(gòu)。一個(gè)典型的類(lèi)型系統(tǒng)通常...
    夏海社長(zhǎng)閱讀 9,376評(píng)論 1 5
  • Go語(yǔ)言通過(guò)自定義結(jié)構(gòu)的方式來(lái)實(shí)現(xiàn)新的類(lèi)型,結(jié)構(gòu)體是類(lèi)型中帶有成員的復(fù)合類(lèi)型。 Go語(yǔ)言使用結(jié)構(gòu)體和結(jié)構(gòu)體成員來(lái)描...
    JunChow520閱讀 582評(píng)論 0 1
  • Go語(yǔ)言中沒(méi)有“類(lèi)”的改變,不支持類(lèi)的“繼承”等面向?qū)ο蟾拍?。Go語(yǔ)言中通過(guò)結(jié)構(gòu)體的內(nèi)嵌再配合接口比面向?qū)ο蟾哂?..
    Cici冬雪閱讀 2,741評(píng)論 0 0
  • 結(jié)構(gòu)(struct) 由于在GO中沒(méi)有class的關(guān)鍵字,也就是其它語(yǔ)言經(jīng)常在面向?qū)ο笾惺褂玫姆矫?,但GO是通過(guò)s...
    astarblog閱讀 5,519評(píng)論 0 0
  • 概述在 Go 語(yǔ)言中,如果一個(gè)結(jié)構(gòu)體和一個(gè)嵌入字段同時(shí)實(shí)現(xiàn)了相同的接口會(huì)發(fā)生什么呢?我們猜一下,可能有兩個(gè)問(wèn)題: ...
    isgiker閱讀 18,918評(píng)論 1 13

友情鏈接更多精彩內(nèi)容