博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go 结构体
阅读量:4326 次
发布时间:2019-06-06

本文共 2866 字,大约阅读时间需要 9 分钟。

Go结构体

结构体是将多个容易类型的命令变量组合在一起的聚合数据类型。

每个变量都成为该结构体的成员变量。

可以理解为Go语言的结构体struct和其他语言的class有相等的地位,但是Go语言放弃大量面向对象的特性,所有的Go语言类型除了指针类型外,都可以有自己的方法,提高了可扩展性。

案例:

package mainimport "fmt"type Person struct{    Name string    Age int} func main(){    var p1 Person    p1.Name = "Yven"    p1.age = 19    fmt.Println(p1.Name,p2.age)}

成员变量

访问控制机制

如果一个结构体的成员变量名称是首字母大写的,那么这个变量是可导出的。(即在其他包可以访问到)

一个结构体可以同时包含可导出和不可到处的成员变量。

type Person struct {    Name string  //不可导出    age int      // 可导出}

限制

命名结构体类型s不可以定义一个拥有相同结构体类型s的成员变量,也就是一个聚合类型不可以包含它自己。但是s中可以定义一个s的指针类型,即*s。

type Person struct {    Name string    p1 Person    //错误    p2 *person   //正确}

结构内嵌(匿名字段)

Go语言中没有像java,python中继承的概念,不过他有一个类似的功能,结构内嵌。

案例:

package mainimport "fmt"type Person struct{    Name string    Age int} type Student struct{    Person    Class string}func main(){    var stu Student    stu.Name = "Yven"    stu.Age = 20    stu.Class = "计算机152"    fmt.Println(stu.Name, stu.Age, stu.Class)}

如果嵌入结构的字段和外部结构的字段相同,那么,想要修改嵌入结构的字段值需要加上外部结构中声明的嵌入结构名称。

案例:

package mainimport "fmt"type Person struct{    Name string    Age int} type Student struct{    Person    Class string    Name string}func main(){    var stu Student    stu.Name = "Yven"    stu.Person.Name = "Yven_lae"    stu.Age = 20    stu.Class = "计算机152"}

Go语言中没有构造方法,但是可以通过工厂模式来解决这个问题,案例如下:

package mainimport "fmt"type Person struct{    Name string    Age int} func NewPerson(name string,age int) *Person{    person := &Person{name,age}    return person}func main(){    p := NewPerson("Yven", 18)    fmt.Println(p.name, p.age) //输出 Yven 18}

方法

Go中除了指针和interface以外的所有类型都可以有方法,不仅仅是struct

方法的定义方式:

func (r ReceiverType) funcName(parameters)(results)

简单案例验证所有类型都可以拥有方法:

package mainimport "fmt"type Int int //没办法直接使用int来进行验证,不过可以对int进行封装后来测试func (a Int) compare(b Int) bool}{    return a < b}func main(){    a := 2    b := 5    fmt.Println(a.compare(b))}

方法的声明和普通函数的声明类似,知识在函数名字前面多加了一个参数,这个参数把这个方法绑定在该参数对应的类型上。该参数成为方法的接受者

案例:

type Person struct{    Name string    Age int}func (p Person) eat(n string){    fmt.Printf("%v 吃了 %v",p.Name,n)}

指针接受者的方法

由于主调函数会复制每一个实参变量,或者如果一个实参太大而我们希望避免复制整个实参,因此我们必须使用指针来传递变量的地址。这也同样适用于更新接收者我们将它绑定到指针类型。在调用方法的时候,编译器会对变量进行隐式转换。

总结一下结构体方法可以成功调用的条件:

  • 实参接收者和形参接收者是同一类型,比如都是T或者都是*T。(1,4,5,7)
  • 实参接收者是T类型的变量而形参接收者是*T类型,编译器会隐式的获取变量的地址(3)。
  • 实参接收者是T类型而形参接收者是T类型,编译器会隐式的获取实际的取值。(2,6)其中8编译过程报错的原因是:编译器对T类型转化为T类型的隐式转化,只有实参接收者是变量才可以成功,因为无法获取临时变量的地址。
type Point struct {    X int    Y int}func (p Point) Print() {    fmt.Println(p.X, p.Y)}func (p *Point) ScaleBy(factor int) {    p.X *= factor    p.Y *= factor}func main() {    p := Point{1,1}    ptr := &p    p.Print()   //1. 正确    ptr.Print() //2. 正确    p.ScaleBy(2)      //3. 正确    ptr.ScaleBy(2)    //4. 正确    Point{1,1}.Print()    //5. 正确    (&Point{1,1}).Print() //6. 正确    (&Point{1,1}).ScaleBy( 2) //7. 正确    Point{1,1}.ScaleBy( 2)    //8. 错误}

转载于:https://www.cnblogs.com/louyefeng/p/11316903.html

你可能感兴趣的文章
Lunix文件的读写权限问题
查看>>
Liferay 7:portlet name
查看>>
PostgreSQL9.6.3的REDIS测试
查看>>
解决pycharm问题:module 'pip' has no attribute 'main'
查看>>
002 lambda表达式
查看>>
springboot添加自定义注解
查看>>
POJ 2391 Ombrophobic Bovines ( 经典最大流 && Floyd && 二分 && 拆点建图)
查看>>
JavaScript数组方法之reduce
查看>>
Linux常用命令之文件搜索命令
查看>>
thinkphp自定义权限管理之名称判断
查看>>
C++ ORM ODB 入门介绍(一)
查看>>
C#_02.14_基础五_.NET类
查看>>
Flask 学习资源
查看>>
Android SDK下载和更新失败的解决方法 分类: Android...
查看>>
MVC2 强类型的 HTML Helper
查看>>
开发 Windows 8 应用 - 0 - windows 8 开发资源
查看>>
生成二维码图片的工具类
查看>>
Surface Pro 4远程桌面分辨率问题
查看>>
【转】包管理器Bower详细讲解
查看>>
JS膏集02
查看>>