Penjelasan terperinci tentang Struktur (struktur) di Golang

青灯夜游
Lepaskan: 2022-11-17 20:49:12
ke hadapan
3107 orang telah melayarinya

Penjelasan terperinci tentang Struktur (struktur) di Golang

Bahasa Go menyediakan sokongan untuk struct struct, terjemahan bahasa Cina dipanggil 结构体, ialah jenis komposit seperti tatasusunan, bukan jenis rujukan. [Cadangan berkaitan: Tutorial Video Go]

Struktur dalam bahasa Go adalah serupa dengan struct dalam bahasa C atau kelas (kelas) dalam bahasa pengaturcaraan berorientasikan objek lain, dan boleh menentukan medan (atribut) ) dan kaedah, tetapi ia juga sangat berbeza dan memerlukan kajian mendalam untuk membezakan perbezaan antara mereka.

Perhatikan perbezaan antara jenis komposit dan jenis rujukan. Ini juga harus menjadi perbezaan antara lulus nilai dan hantaran rujukan.

Definisi

Menggunakan kata kunci struct, anda boleh mentakrifkan struktur, dan ahli dalam struktur dipanggil medan atau atribut struktur.

type Member struct {
    id          int
    name, email string
    gender, age int
}
Salin selepas log masuk

Dalam kod di atas, kami mentakrifkan struktur yang mengandungi 5 medan Anda boleh melihat bahawa jenis yang sama name dan email, gender dan age berada pada baris yang sama ditakrifkan. dalam, tetapi tabiat pengaturcaraan yang lebih baik ialah mentakrifkan hanya satu medan dalam setiap baris, seperti:

type Member struct {
    id     int
    name   string
    email  string
    gender int
    age    int
}
Salin selepas log masuk

Sudah tentu, struktur juga tidak boleh mengandungi sebarang medan, dipanggil 空结构体, struct{} mewakili a Struktur kosong Ambil perhatian bahawa tidak masuk akal untuk mentakrifkan struktur kosong secara langsung, bagaimanapun, dalam pengaturcaraan serentak, struct{} boleh digunakan sebagai semaphore untuk komunikasi antara saluran.

ch := make(chan struct{})
ch <- struct{}{}
Salin selepas log masuk

Gunakan

Dalam contoh di atas, kami menentukan jenis struktur Ahli, dan kemudian kami boleh mencipta pembolehubah jenis tersuai ini.

mentakrifkan pembolehubah secara langsung Kaedah penggunaan ini tidak memberikan nilai awal kepada medan, jadi semua medan akan diberikan nilai sifar jenisnya sendiri secara automatik ialah rentetan kosong "", Nilai umur ialah 0. name

var m1 Member//所有字段均为空值
Salin selepas log masuk
Gunakan literal untuk mencipta pembolehubah dengan cara ini, anda boleh menetapkan nilai awal kepada ahli struktur dalam pendakap. Satu ialah Yang pertama adalah untuk menetapkan nilai dalam susunan medan dalam struktur

dalam kod di bawah menggunakan kaedah ini banyak medan, setiap medan mesti diberikan nilai, yang akan menyusahkan kaedah lain ialah menggunakan nama medan untuk menentukan tugasan medan, seperti penciptaan pembolehubah m2 dengan cara ini , untuk medan lain yang tidak ditentukan, nilai sifar jenis medan digunakan sebagai nilai permulaan. m3

var m2 = Member{1,"小明","xiaoming@163.com",1,18} // 简短变量声明方式:m2 := Member{1,"小明","xiaoming@163.com",1,18}
var m3 = Member{id:2,"name":"小红"}// 简短变量声明方式:m3 := Member{id:2,"name":"小红"}
Salin selepas log masuk
Mengakses medan

Dengan menggunakan nama pembolehubah dan menggunakan koma

, anda boleh mengakses medan dalam jenis struktur, menetapkan nilai kepada medan atau mendapatkan semula medan . Alamat (&) operasi. (.)

fmt.Println(m2.name)//输出:小明
m3.name = "小花"
fmt.Println(m3.name)//输出:小花

age := &m3.age
*age = 20
fmt.Println(m3.age)//20
Salin selepas log masuk
Struktur penunjuk

Struktur, seperti tatasusunan, diluluskan mengikut nilai Contohnya, apabila tatasusunan atau struktur diluluskan sebagai parameter sebenar kepada parameter formal fungsi, a salinan akan dibuat, jadi untuk meningkatkan prestasi, tatasusunan biasanya tidak dihantar terus ke fungsi, tetapi hirisan (jenis rujukan) digunakan sebagai ganti apabila menghantar struktur ke fungsi,

boleh digunakan. 指针结构体

Struktur penunjuk, iaitu penunjuk kepada struktur Apabila mengisytiharkan pembolehubah struktur, tambah tanda * sebelum jenis struktur untuk mengisytiharkan penunjuk kepada struktur, seperti:

<. 🎜>Perhatikan bahawa jenis penunjuk ialah jenis rujukan Apabila mengisytiharkan penunjuk struktur, jika ia tidak dimulakan, nilai awal adalah nil Hanya selepas permulaan, medan itu boleh diakses atau diberikan nilai.

Selain itu, menggunakan fungsi new() terbina dalam Go, anda boleh memperuntukkan memori untuk memulakan struktur dan mengembalikan penuding memori yang diperuntukkan Kerana ia telah dimulakan, anda boleh mengakses terus padang.
var m1 *Member
m1.name = "小明"//错误用法,未初始化,m1为nil

m1 = &Member{}
m1.name = "小明"//初始化后,结构体指针指向某个结构体地址,才能访问字段,为字段赋值。
Salin selepas log masuk

Kami tahu bahawa jika anda memindahkan struktur ke fungsi, anda hanya akan membuat salinan struktur Jika anda mengubah suai nilai medan struktur dalam fungsi, struktur luar akan tidak terjejas, dan jika Jika penunjuk struktur dihantar ke fungsi, sebarang pengubahsuaian yang dibuat pada struktur menggunakan penunjuk dalam fungsi akan menjejaskan struktur yang ditunjukkan oleh penunjuk.
var m2 = new(Member)
m2.name = "小红"
Salin selepas log masuk

Keterlihatan
func main() {
    m1 := Member{}
    m2 := new(Member)
    Change(m1,m2)
    fmt.Println(m1,m2)
}

func Change(m1 Member,m2 *Member){
    m1.Name = "小明"
    m2.Name = "小红"
}
Salin selepas log masuk

Dalam contoh di atas, kami mentakrifkan huruf pertama nama medan struktur menjadi huruf kecil, yang bermaksud bahawa medan ini berada dalam

dan oleh itu tidak boleh berada dalam pakej lain diakses, hanya akses dalam pakej dibenarkan.

包外不可见Dalam contoh berikut, kami mengisytiharkan Ahli dalam pakej ahli dan kemudian mencipta pembolehubah dalam pakej utama Walau bagaimanapun, memandangkan medan struktur tidak kelihatan di luar pakej, kami tidak boleh menetapkan nilai awal medan dan tidak boleh menekan Sama ada medan ditetapkan oleh indeks atau ditetapkan, ralat panik akan berlaku.

Oleh itu, jika anda ingin mengakses medan struktur dalam pakej lain dalam satu pakej, ia mestilah pembolehubah yang bermula dengan huruf besar, iaitu pembolehubah yang dieksport, seperti:
package member
type Member struct {
    id     int
    name   string
    email  string
    gender int
    age    int
}

package main

fun main(){
    var m = member.Member{1,"小明","xiaoming@163.com",1,18}//会引发panic错误
}
Salin selepas log masuk

tags

type Member struct {
    Id     int
    Name   string
    Email  string
    Gender int
    Age    int
}
Salin selepas log masuk
Apabila menentukan medan struktur, sebagai tambahan kepada nama medan dan jenis data, anda juga boleh menggunakan backticks untuk mengisytiharkan meta-maklumat untuk medan struktur dipanggil Tag dan digunakan dalam fasa kompilasi Berkaitan dengan medan, contohnya, kami mengubah suai struktur dalam contoh di atas kepada:

type Member struct {
    Id     int    `json:"id,-"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Gender int    `json:"gender,"`
    Age    int    `json:"age"`
}
Salin selepas log masuk

上面例子演示的是使用encoding/json包编码或解码结构体时使用的Tag信息。

Tag由反引号括起来的一系列用空格分隔的key:"value"键值对组成,如:

Id int `json:"id" gorm:"AUTO_INCREMENT"`
Salin selepas log masuk

特性

下面总结几点结构体的相关特性:

值传递

结构体与数组一样,是复合类型,无论是作为实参传递给函数时,还是赋值给其他变量,都是值传递,即复一个副本。

没有继承

Go语言是支持面向对象编程的,但却没有继承的概念,在结构体中,可以通过组合其他结构体来构建更复杂的结构体。

结构体不能包含自己

一个结构体,并没有包含自身,比如Member中的字段不能是Member类型,但却可能是*Member。

方法

在Go语言中,将函数绑定到具体的类型中,则称该函数是该类型的方法,其定义的方式是在func与函数名称之间加上具体类型变量,这个类型变量称为方法接收器,如:

注意,并不是只有结构体才能绑定方法,任何类型都可以绑定方法,只是我们这里介绍将方法绑定到结构体中。

func setName(m Member,name string){//普通函数
    m.Name = name
}

func (m Member)setName(name string){//绑定到Member结构体的方法
    m.Name = name
}
Salin selepas log masuk

从上面的例子中,我们可以看出,通过方法接收器可以访问结构体的字段,这类似其他编程语言中的this关键词,但在Go语言中,只是一个变量名而已,我们可以任意命名方法接收器

调用结构体的方法,与调用字段一样:

m := Member{}
m.setName("小明")
fmt.Println(m.Name)//输出为空
Salin selepas log masuk

上面的代码中,我们会很奇怪,不是调用setName()方法设置了字段Name的值了吗?为什么还是输出为空呢?

这是因为,结构体是值传递,当我们调用setName时,方法接收器接收到是只是结构体变量的一个副本,通过副本对值进行修复,并不会影响调用者,因此,我们可以将方法接收器定义为指针变量,就可达到修改结构体的目的了。

func (m *Member)setName(name string){/将Member改为*Member
    m.Name = name
}

m := Member{}
m.setName("小明")
fmt.Println(m.Name)//小明
Salin selepas log masuk

方法和字段一样,如果首字母为小写,则只允许在包内可见,在其他包中是无法访问的,因此,如果要在其他包中访问setName,则应该将方法名改为SetName

组合

我们知道,结构体中并没有继承的概念,其实,在Go语言中也没有继承的概念,Go语言的编程哲学里,推荐使用组合的方式来达到代码复用效果。

什么是组合

组合,可以理解为定义一个结构体中,其字段可以是其他的结构体,这样,不同的结构体就可以共用相同的字段。

注意,在记得我们前面提过的,结构体不能包含自身,但可能包含指向自身的结构体指针。

例如,我们定义了一个名为Animal表示动物,如果我们想定义一个结构体表示猫,如:

type Animal struct {
    Name   string  //名称
    Color  string  //颜色
    Height float32 //身高
    Weight float32 //体重
    Age    int     //年龄
}
//奔跑
func (a Animal)Run() {
    fmt.Println(a.Name + "is running")
}
//吃东西
func (a Animal)Eat() {
    fmt.Println(a.Name + "is eating")
}

type Cat struct {
    a Animal
}

func main() {
    var c = Cat{
	    a: Animal{
            Name:   "猫猫",
            Color:  "橙色",
            Weight: 10,
            Height: 30,
            Age:    5,
        },
    }
    fmt.Println(c.a.Name)
    c.a.Run()
}
Salin selepas log masuk

可以看到,我们定义Cat结构体时,可以把Animal结构体作为Cat的字段。

匿名字段

上面的例子,我们看到,把Animal结构体作为Cat的字段时,其变量名为a,所以我们访问Animal的方法时,语法为c.a.Run(),这种通过叶子属性访问某个字段类型所带的方法和字段用法非常繁琐。

Go语言支持直接将类型作为结构体的字段,而不需要取变量名,这种字段叫匿名字段,如:

type Lion struct {
	Animal //匿名字段
}

func main(){
    var lion = Lion{
        Animal{
            Name:  "小狮子",
            Color: "灰色",
        },
    }
    lion.Run()
    fmt.Println(lion.Name)
}
Salin selepas log masuk

通过上面例子,可以看到,通过匿名字段组合其他类型,而后访问匿名字段类型所带的方法和字段时,不需要使用叶子属性,非常方便。

小结

在Go语言编程中,结构体大概算是使用得最多的数据类型了,通过定义不同字段和方法的结构体,抽象组合不同的结构体,这大概便是Go语言中对面向对象编程了。

原文地址:https://juejin.cn/post/6844903814168838151

更多编程相关知识,请访问:编程视频!!

Atas ialah kandungan terperinci Penjelasan terperinci tentang Struktur (struktur) di Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan