Golang入门学习(10)

Go的第10课——类型定义和结构体

类型定义

定义语法跟之前的函数类型一样,使用 type 关键字

1
type newtype oldtype

这里我们是给 oldtype 定义了一个别名,相当于是 typedef 只是 go 里面相对于 C 是反着写的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

type pid_t int

func main() {
var pid pid_t
pid = 1
if pid == 1 {
fmt.Println("SYSTEM PROCESS")
} else {
fmt.Println("COMMON PROCESS")
}
}
/*
SYSTEM PROCESS
*/

结构体

基本介绍

go语言没有面向对象的概念了,但是可以使用结构体来实现,面向对象编程的一些特性,例如:继承、组合等特性。

在这里我们结合上面的定义去创建一个结构体类型。

1
2
3
4
5
6
type struct_identifier struct{
member1 type1
member2 type2
...
membern typen
}

demo

随便定义一个结构体玩玩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

type Person struct {
age int
name string
height int
}

func main() {
var person Person
person.name = "xia0ji233"
person.age = 22
person.height = 185
fmt.Println(person)
}
/*
{22 xia0ji233 185}
*/

结构体成员在没有赋值之前都是默认值。

结构体初始化

第一个就是按照上面的 demo 给成员一个一个赋值。

第二个就是使用键值对的方式初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"
)

type Person struct {
age int
name string
height int
}

func main() {
var person = Person{age: 18, name: "xia0ji233", height: 185}
fmt.Println(person)
}
/*
{18 xia0ji233 185}
*/

还有一个应该是可以使用成员方法的,这个不叫构造方法,因为它没有面向对象的概念,所以说也只能是定义一个成员方法去给它初始化。

结构体指针

基本用法

就和普通类型的指针差不多的用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

type Person struct {
age int
name string
height int
}

func main() {
var person = Person{age: 18, name: "xia0ji233", height: 185}
var p *Person
p = &person
fmt.Printf("name:%v\n", (*p).name)
fmt.Printf("age:%v\n", (*p).age)
fmt.Printf("height:%v\n", (*p).height)
}
/*
name:xia0ji233
age:18
height:185
*/

new关键字创建结构体指针

我们还可以通过使用 new 关键字对结构体进行实例化,得到的是结构体的地址,也就是指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import "fmt"

type Person struct {
age int
name string
height int
}

func main() {
var p *Person
p = new(Person)
(*p).name = "xia0ji233"
(*p).age = 18
(*p).height = 185
fmt.Printf("name:%v\n", (*p).name)
fmt.Printf("age:%v\n", (*p).age)
fmt.Printf("height:%v\n", (*p).height)
}
/*
name:xia0ji233
age:18
height:185
*/

这里还发现一点,就是 C 语言对于指针访问结构体变量是只能 (*ptr).member 去访问,或者是 ptr->member 这样子的,而 go 就爽了,指针和结构体类型都是可以直接用 . 来访问成员变量的,可能是因为对指针做了限制,导致 ptr.member 写法就没什么歧义,因此可以。

方法

基本用法

go 语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向对象里面有类方法等概念。我们也可以声明一些方法,属于某个结构体。

Go中的方法,是一种特殊的函数定义于struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。

通俗的讲,方法就是有接收者的函数。

语法格式如下:

1
2
3
type mytype struct{}
func (recv mytype) my_method(para) return_type {}
func (recv *mytype) my_method(para) return_type {}

和一般的函数对比起来,多了一个接受类型(recv) 其实这也可以看成一个参数,只不过因为是结构体主动调用的,所以这个参数可以不用我们主动传。

如果我们需要修改成员那就使用指针传参,如果不需要那么可以直接结构体传参,下面实现一个 init 的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

type Person struct {
age int
name string
height int
}

func (recv *Person) init(age int, name string, height int) {
*recv = Person{
age: age,
name: name,
height: height,
}
}

func main() {
var p *Person
p = new(Person)
p.init(18, "xiaoji233", 185)
fmt.Printf("name:%v\n", (*p).name)
fmt.Printf("age:%v\n", (*p).age)
fmt.Printf("height:%v\n", (*p).height)
}
/*
name:xiaoji233
age:18
height:185
*/

注意事项

  • 方法的receiver type并非一定要是struct类型,type定义的类型别名、slice,map,channel,func类型等都可以。
  • struct结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。
  • 方法有两种接收类型:(T Type)和(T*Type),它们之间有区别。
  • 方法就是函数,所以Go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
  • 如果receiver是一个指针类型,则会自动解除引用。
  • 方法和type是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过receiver建立起关联关系。

经过自己实验呢,发现基础数据类型确实不能,但是自己往基础类型创建一个别名就可以使用,弹幕里面有一句话叫 “扩展方法”,姑且认为是这样吧,方法和函数差不多,也不支持重载。

这边再写一个小例子巩固一下,弥补一下之前 int 转 string 不能强转的缺陷,为它写一个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

type pid_t int

func (recv pid_t) tostring() string {
return fmt.Sprintf("%d", recv)
}

func main() {
var s pid_t
s = 2147483647
var q = "value:" + s.tostring()
fmt.Println(q)
}
/*
value:2147483647
*/
文章目录
  1. 1. 类型定义
  2. 2. 结构体
    1. 2.1. 基本介绍
    2. 2.2. demo
    3. 2.3. 结构体初始化
    4. 2.4. 结构体指针
      1. 2.4.1. 基本用法
      2. 2.4.2. new关键字创建结构体指针
    5. 2.5. 方法
      1. 2.5.1. 基本用法
      2. 2.5.2. 注意事项
|