一、结构
- 1、结构体类似于Java中 无方法的类。
- 2、结构体是
值类型,值类型,值类型!!重要的事情强调好几遍!!
,可以通过new
函数实例化(得到的是引用类型)。 - 3、组成结构体的元素称为字段(fields),每个字段都有一个类型和名字,
名字是唯一的
。 - 4、结构体的字段可以是任何类型:可以使结构体本身,也可以是函数或者接口。
- 5、对于嵌套结构体(类似于继承),字段是可以重载的
1、实例化
--使用new (得到的是指针类型)
使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针:
var t *T = new(T)
type struct1 struct {
i1 int
f1 float32
str string
}
var stru *struct1 = new(struct1)
--对象字面量方式 (得到的是值类型)
type Interval struct {
start int
end int
}
intr1 := Interval{0, 3} // __(得到的是值类型)__
intr2 := Interval{end:5, start:1} // __(得到的是值类型)__
intr3 := &Interval{end:5} // __(得到的是指针类型)__
表达式 new(Type) 和 &Type{} 是等价的,得到的都是指针。
切记,不要用make关键字,会引发编译错误
2、指针类型的实例赋值
pers2 := new(Person)
pers2.lastName = "Woodward"
(*pers2).lastName = "Woodward" // 这也是合法的
3、匿名(或内嵌)字段
匿名字段:字段可以没有名字,但是类型是必须的,此时类型就是字段的名字。
匿名字段本身可以是一个 结构体。
type struct01 struct { a,b int }
type struct02 struct {
struct01 // 内嵌结构体
a int // 重载 struct01 中的 a 字段
int // 匿名字段,以类型 作为 名字
}
# 实例化:
str02 := new struct02()
str02.struct01.a = 123
str02.a = 1
str02.int = 2 // 给匿名字段赋值
str02.b = 3
二、方法
- 1、Go中没有
this
的概念,方法通过接受者(receiver)
与类型关联。 - 2、接受者可以是
指针
( Go 会自动解引用
,解释成对应的值 )也可以是值类型
,建议用引用类型(节省内存,速度快) - 2、方法可以不与类型在同一个文件中,但是必须在同一个包中。
- 3、类型 + 方法 组合成一个
类
的概念。 - 4、同一个接受者类型上不准有重名的方法。
# 定义格式:
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
# 例子:
type struct01 struct { a, b int } // 定义一个 结构体
// 以该结构体作为接受者,定义一个方法 sum
func (stru01 *struct01) sum() int {
// stru01 相当于 this 的意思
return stru01.a + stru01.b
}
func (_ *struct01) saySth() {
fmt.Println('这个方法不使用到结构体struct01中的任何字段,所以 接受者的实例可以用 _ 来替代')
}
定义在
值
上的方法,既可以通过值
调用,也可以通过指针
调用,因为指针会解引用;
定义在指针
上的方法,只能通过指针
调用,不能通过值调用。
三、结构体的遍历
package main
import (
"fmt"
"reflect"
)
type person struct {
name string
age int
}
func main() {
v := reflect.ValueOf(person{"Diana", 30})
count := v.NumField()
for i := 0; i < count; i++ {
f := v.Field(i)
switch f.Kind() {
case reflect.String:
fmt.Println(f.String())
case reflect.Int:
fmt.Println(f.Int())
}
}
}