Yayako's Blog

「Shooting for the stars when I couldn't make a killing.」

仅作java2go的简单记录,有错误烦请提出

合集整理:Java转Go的学习-合集

demo已上传git:https://gitee.com/yayako/go-learning.git

结构体与其方法

结构体

结构体的定义

1
2
3
type StructName struct {
// 属性
}

几个点:

  • 结构名和字段名首字母大小写同样意味着访问权限,大写表示共有,小写表示当前包私有。

  • 定义结构体时允许成员字段没有字段名,这些字段称为匿名字段,且类型必须唯一,其他包也无法访问匿名字段。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type Nameless struct {
    string
    int
    *Address
    }

    type Address struct {
    Country string
    City string
    }

    匿名字段使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    n := Nameless{
    string: "",
    Address: &Address{
    Country: "",
    City: "",
    },
    }
    n.int = 1
    n.Address = &Address{}

结构体的实例化

假设有结构体如下

1
2
3
4
5
6
7
8
9
10
type Person struct {
Name string
Age int
Addr Address
}

type Address struct {
Country string
City string
}

几种实例化/初始化方式

1
2
3
4
5
6
7
8
9
10
11
12
13
var p = new(Person)
var p *Person
var p = &Person{}
p := &Person{}

// 也可以简化初始,属性名称要么都写,要么都省略
var p = &Person{
/* Name: */ "李四",
/* age: */ 18,
&Address{
Country: "中国",
},
}

在go中支持对结构体指针直接使用 . 来访问结构体成员,例如 p.name 在底层实际上是 (*p).name

另外,当访问结构体成员时,会先在结构体中查找该字段,找不到再去匿名结构中查找,如果多个嵌套结构体内都包含相同的字段,则会报错 ambiguous selector

1
2
3
// 以下两行代码是同一效果
p1.City = "浙江"
p1.Address.City = "浙江"

最后一点需要注意的是,结构体是值类型

json与结构体的相互转换

在Java中,想要将实例json序列化通常需要使用第三方包的方法,例如阿里的fastjson。而在go中则只需要使用tag进行标记,再通过自由的json包序列化/反序列化即可。

不过需要注意私有字段不会被序列化

如下结构体,定义了json tag做序列化时的kv映射

1
2
3
4
type Student struct {
ID int `json:"id"` // 定义tag做json的kv映射
Person `json:"person"` // 继承Person类
}

序列化示例,主要是 Marshal 方法

1
2
3
4
5
6
7
8
9
10
11
12
s := &Student{
ID: 0,
Person: Person{
Name: "小红",
age: 22,
Address: &Address{},
},
}
// 1. 将结构体转换为byte数组
jsonByte, _ := json.Marshal(s)
// 2. byte数组转json字符串
jsonStr := string(jsonByte) // {"id":0,"person":{"Name":"小红","Country":"","City":""}}

反序列化示例,主要是 Unmarshal 方法

1
2
var s *Student
err := json.Unmarshal([]byte(jsonStr), &s) // &main.Student{ID:0, Person:main.Person{Name:"小红", age:22, Address:(*main.Address)(0xc000004600)}}

结构体方法

在go中,没有类的概念,但是可以给类型(结构体、自定义类型)定义方法 —— 定义了接收者的函数。接收者就类似java中的this。

定义格式

1
2
3
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
// 方法体
}

以Person为例

1
2
3
4
func (this *Person) SetInfo(name string, age int) {
this.Name = name
this.age = age
}

使用

1
p.SetInfo("哈哈", 22)

继承

go中继承的实现挺令人无语的,通过嵌套实现

假设有Person的子类Student,则Student的结构体需要将Person设为自己的属性

1
2
3
4
type Student struct {
ID
Person // 继承Person类
}

由此创建的Student实例即可调用Person的方法

image-20210205182157082

评论