构造函数:返回一个结构体变量的函数 Go语言 面向接口编程 结构体是值类型,赋值的时候都是拷贝 package mainimport "fmt"// 构造函数type person struct {name stringage int}type dog struct {name string}/
构造函数:返回一个结构体变量的函数
Go语言 面向接口编程
结构体是值类型,赋值的时候都是拷贝
package main
import "fmt"
// 构造函数
type person struct {
name string
age int
}
type dog struct {
name string
}
// 构造函数:约定成俗new开头
// 返回的是结构体还是结构体指针
// 当结构体比较大的时候尽量使用结构体指针,减少程序的内存开销
func newPerson(name string, age int) person{
return person{
name: name,
age: age,
}
}
func newDog(name string) dog {
return dog{
name: name,
}
}
func main(){
p1 := newPerson("林黛玉", 16)
p2 := newPerson("贾宝玉", 18)
fmt.Println(p1, p2)
d1 := newDog("大黄")
fmt.Println(d1) // {大黄}
}
方法和接收者
方法
package main
import "fmt"
// 方法
type dog struct {
name string
}
// 构造函数
func newDog(name string) dog {
return dog{
name: name,
}
}
// 方法是作用于特定类型的函数
// 接收者表示的是调用该方法的具体类型变量,多用类型名首字母小写表示
func (d dog)wang(){
fmt.Println("汪汪汪...")
fmt.Printf("%s:汪汪汪\n", d.name)
}
func main(){
d1 := newDog("小白")
d1.wang()
}
格式:
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
函数体
}
什么时候应该使用指针类型接收者
- 需要修改接收者中的值
- 接收者是拷贝代价比较大的大对象
- 保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。
package main
import (
"fmt"
)
// 方法
// 标识符:变量 函数名 类型名 方法名
// Go语言中如果标识符首字母是大写的,就表示外部包可见(暴露的 公有的)
// Dog 这是一个狗的结构体
// type Dog struct {
type dog struct {
name string
}
type person struct {
name string
age int
}
// 构造函数
func newDog(name string) dog {
return dog{
name: name,
}
}
func newPerson(name string, age int) person{
return person{
name: name,
age: age,
}
}
// 方法是作用于特定类型的函数
// 接收者表示的是调用该方法的具体类型变量,多用类型名首字母小写表示
func (d dog)wang(){
fmt.Println("汪汪汪...")
fmt.Printf("%s:汪汪汪\n", d.name)
}
// 使用值接收者:传拷贝进去
func (p person) guonian(){
p.age ++
}
// 指针接收者:传内存地址进去
func (p *person) zhenguonian(){
p.age++
}
func (p *person)dream(){
fmt.Println("改变世界改变自己")
}
func main(){
d1 := newDog("小白")
d1.wang()
p1 := newPerson("理想", 18)
fmt.Println(p1.age) // 18
p1.guonian()
fmt.Println(p1.age) // 18
p1.zhenguonian()
fmt.Println(p1.age) // 19
p1.dream()
}
给自定义类型添加方法
package main
import "fmt"
// 给自定义类型加方法
// 不能给别的包里面的类型添加方法,只能给自己包里的类型添加方法
type myInt int
func (m myInt)hello(){
fmt.Println("我是一个Int")
}
func main(){
m := myInt(100) // int8(10)
// m := 10 // int
m.hello()
}
问题
package main
import "fmt"
// 结构体问题
// myInt(100)是什么
type myInt int
func (m myInt)hello(){
fmt.Println("我是一个Int")
}
type person struct {
name string
age int
}
func main(){
// 声明一个int32类型的变量x,它的值是10
// 方法1
// var x int32
// x = 10
// 方法2
// var x int32 = 10
// var x = 10
// 方法3
// var x = int32(10)
// 方法4
// x := int32(10)
// fmt.Println(x)
// 声明一个myInt类型的变量m,它的值是100
// 方法1:
// var m myInt
// m = 100
// 方法2:
// var m myInt = 100
// 方法3:
// var m = myInt(100)
// 方法4:
// m := myInt(100) // 强制类型转换
// fmt.Println(m)
// m := myInt(100) // int8(10)
// // m := 10 // int
// m.hello()
// 问题2:结构体初始化
// 方法1:
var p person // 声明一个person类型的变量p
p.name = "理想"
p.age = 18
fmt.Println(p)
var p1 person
p1.name = "奈莎"
p1.age = 12
fmt.Println(p1)
// 方法2
s1 := []int{1,2,3}
m1 := map[string]int{
"stu1": 100,
"stu2": 88,
"stu3": 99,
}
fmt.Println(s1, m1)
// 键值对初始化
var p2 = person{
name: "仲尼",
age: 15,
}
fmt.Println(p2)
// 值列表初始化
var p3 = person{
"黛玉",
18,
}
fmt.Println(p3)
}
// 问题3:为什么要有构造函数
func newPerson(name string, age int)person{
// 别人调用我,我能给它一个person类型的变量
// tmpP := person{
return person{
name: name,
age: age,
}
// return tmpP
}
// func newPerson(name string, age int)*person{
// // 别人调用我,我能给它一个person类型的变量
// // tmpP := person{
// return &person{
// name: name,
// age: age,
// }
// // return tmpP
// }