GolangStruct使用
Golang中Struct使用浅谈
一、golang里面的struct
- Go面向对象编程的核心(struct)
Go 语言是一种静态类型的编程语言,这意味着,编译器需要在编译时知晓程序里每个值的类型。在Go中,通过使用关键字 struct,可以让用户创建一个自定义结构类型,并且结构类型允许通过组合一系列固定且唯一的字段甚至其他结构体来完成声明,便于用户定义具备丰富属性和操作的类型。
Go语言的结构体(struct)和其他语言的类(class)有同等的地位,给Go语言的面向对象编程提供了便利,但Go语言放弃了包括继 承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性。
二、struct的基本使用
-
struct作为Go语言类型声明的核心,需要和Type字段功能组成类型系统语法的声明工作,基本的格式如下:
// 声明一个空类型 type structName struct{} //带有成员变量的类型 type structName struct{ propertiesName type; } //组合类型【嵌套类型】 type structNewName struct{ propertiesName1 type; propertiesName2 structName;//上面的结构类型作为新类型的属性 } // 声明多个类型【归类组合】 type ( structA struct{ propertiesNameA type; } structB struct{ propertiesNameB type; } ... )
-
使用示例
申明一个类型:Cat,拥有属性name,然后定义一个行为方法Roar,用来发出叫声。我们可以看到,使用Cat类型时,需要进行初始化,类似Java中的获取一个实例对象,方法的调用使用类名.方法(参数类型)。
package main import "fmt" type Cat struct { Name string } func (c *Cat) Roar() { fmt.Println("喵喵喵") } func main() { var cat = &Cat{Name: "cily"} cat.Roar() }
三、嵌套struct【组合】使用
-
结构形式
type ( structA struct{ propertiesNameA1 type; propertiesNameA2 structB; //结构类型作为新类型的属性 } structB struct{ propertiesNameB1 type; propertiesNameB2 structC; } structC struct{ propertiesNameC type; } )
-
使用场景
嵌套struct是Go语言中组合语法,通过组合的特性可以组合声明多个属性、多个类型来组成具有丰富特性的新类型,即新对象,可以参考Java中的组合语法进行理解,不过Go的这种组合更简洁,便于理解,也正是这种特性使得Go语言的面向对象得以丰富。
-
示例
package main import ( "fmt" ) type ( Car struct { factory string price int engine Engine } Engine struct { engineName string } ) var instance *Car func NewCar() *Car { if instance == nil { en := Engine{ engineName: "default", } instance = &Car{ factory: "", price: 0, engine: en, } } return instance } func (c *Car) produceCar(factory string, price int, enName string) { c.price = price c.factory = factory c.engine.engineName = enName } func (c *Car) getCar() { fmt.Println(c) } func main() { car := NewCar() car.produceCar("factory one", 10, "沃尔沃") car.getCar() }
四、踩坑注意
-
在map使用时,特别结合struct场景,很容易因为map的指针的特性和Go底层的一些原理造成神奇的"指针现象",比如下例代码:
package main import ( "fmt" "strconv" ) type ( Strc struct { id int info *Tmp } Tmp struct { id int name string dec string } ) func main() { var stc = make([]*Strc, 0) var pr []Strc for i := 0; i < 5; i { var data = Strc{ id: i, info: &Tmp{ id: i 1, name: "test", dec: strconv.Itoa(i 1) "test", }, } pr = append(pr, data) } for _, i2 := range pr { s := &i2 //核心在这里 stc = append(stc, s) } for i, s := range stc { fmt.Println(i, "--", s.info.id) } }
结果: 0 -- 5 预期结果是1 【i 1】 1 -- 5 预期结果是2 2 -- 5 预期结果是3 3 -- 5 预期结果是4 4 -- 5 预期结果是5
-
修复代码,和map的使用有关,只是在struct中应用时候需要注意,详情可以参考《GO语言设计与实现》
基本原因:
一般来说,使用range遍历map的索引和元素时,会额外创建新的一片内存空间存储切片中的元素,循环中每一次迭代都会被重新赋值而被覆盖,赋值时也会触发复制,因为循环中获取返回变量的地址都完全一样,所以会发生神奇的"指针现象",不应该使用&i2,要么使用&i2[index],或者使用一个临时变量存储s := i2,然后使用&s。
package app import ( "fmt" "strconv" ) type ( Strc struct { id int info *Tmp } Tmp struct { id int name string dec string } ) func DDD() { var stc = make([]*Strc, 0) var pr []Strc for i := 0; i < 5; i { var data = Strc{ id: i, info: &Tmp{ id: i 1, name: "test", dec: strconv.Itoa(i 1) "test", }, } pr = append(pr, data) } for _, i2 := range pr { s := i2 //核心在这里 stc = append(stc, &s) } for i, s := range stc { fmt.Println(i, "--", s.info.id) } }
结果: 0 -- 1 1 -- 2 2 -- 3 3 -- 4 4 -- 5
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfbica
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01