1、Go语言中的一些格式化输出符号
%v —— 只输出所有的值
%+v —— 先输出字段类型,再输出该字段的值
%#v —— 先输出结构体名字值,再输出结构体(字段类型+字段的值)
更多格式化输出符见:https://wenku.baidu.com/view/6393f769862458fb770bf78a6529647d2728343f.html
2、Go语言中方法和函数的区别
go语言中函数与方法的区别:对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递;对于方法,接收者为值类型时,可以直接用指针类型的变量调用方法。
3、Go Method
3.1 go方法的定义
Go的方法是在函数前面加一个接受者,这样编译器就知道这个方法属于哪个类型的了。以下是为一个类型定义一个方法的过程
示例:
package main
import (
"fmt"
)
type Student struct { //定义了一个类型叫 Student。
Name string
Age int
}
//定义了一个值类型为Student的GetName方法
func (stu Student) GetName() string { //为 Student 类型定义了一个方法叫 GetName
return stu.Name
}
//定义了一个指针类型为Student的 SetName方法
func (stu Student) SetName(name string) { //为 Student 类型定义了一个方法叫 SetName,调用时需要传入一个参数
stu.Name = name
}
func (stu *Student) Setname(name string) {
stu.Name = name
}
func main() {
//定义了一个类型为Student的变量
//定义一个变量类型为Student,然后并赋值
var s01 Student
s01 = Student{
Name: "s01",
Age: 18,
}
name := s01.GetName()
fmt.Printf("name=%s\n", name)
s01.SetName("s02") //这里的s01就是,定义方法func (stu *Student) Setname(name string) 里面的stu,Stu就是s01的拷贝
name = s01.GetName()
fmt.Printf("name = %s\n", name)
//(&s01).Setname("s02") 正规写法,下面的写法是GO帮助我们做了取地址的动作
s01.Setname("s03")
name = s01.GetName()
fmt.Printf("name = %s\n", name)
}
*函数和方法的区别,函数不属于任何类型,方法属于特定的类型
*什么时候用值类型或指针类型做为方法的接受者?
1)需要修改接受者中的值的时候
2)接受者是大对象的时候,副本拷贝代价比较大
3)一般来说,通常使用指针类型作为同接受者,就可以了。
示例:
package main
import (
"fmt"
"time"
)
type User struct {
s1 [10000000]int64
s2 [10000000]int64
s3 [10000000]int64
s4 [10000000]int64
}
//func (u User) Set() { 换成值类型
func (u *User) Set() {
for i := 0; i < len(u.s1); i++ {
u.s1[i] = 1
u.s2[i] = 1
u.s3[i] = 1
u.s4[i] = 1
}
}
func main() {
//var u *User = new(User) //初始化指针
var u *User = &User{ //初始化指针
}
start := time.Now().UnixNano()
u.Set()
end := time.Now().UnixNano()
fmt.Printf("cost:%d ns\n", (end - start)/1000)
}
运行结果,运行速度提升近一倍
bogon:struct_copy jianglinguo$ ./struct_copy
cost:408596 ns
bogon:struct_copy jianglinguo$ go build
bogon:struct_copy jianglinguo$ ./struct_copy
cost:181123 ns
3.2 方法的继承
package main
import (
"fmt"
)
type Animal struct {
Name string
Age int
}
func (a * Animal) SetName(name string) {
a.Name = name
}
func (a *Animal) SetAge(age int) {
a.Age = age
}
func (a * Animal) PrintHandle() {
fmt.Printf("a.name = %s a.age = %d\n", a.Name, a.Age)
}
type Bird struct {
//Animal
//Animal *Animal 字段如果不指定名字默认使用Animal
*Animal //*Animal这个是指针要初始化一下,字段如果不指定名字默认使用Animal
}
func (b *Bird) Fly() {
fmt.Printf("name %s is fly\n", b.Name)
}
func main() {
var b *Bird = &Bird{
Animal: &Animal{}, //初始化Animal
}
b.SetName("bird") //bird继承了Animal所以,b就有Animal的方法
b.SetAge(13) //bird继承了Animal所以,b就有Animal的方法
b.Fly() //这个 Fly是bird的方法
}
JSON序列化
package main
import (
"fmt"
"encoding/json"
)
type Animal struct {
Name string
Age int
}
func (a * Animal) SetName(name string) {
a.Name = name
}
func (a *Animal) SetAge(age int) {
a.Age = age
}
func (a * Animal) PrintHandle() {
fmt.Printf("a.name = %s a.age = %d\n", a.Name, a.Age)
}
type Bird struct {
//Animal
//Animal *Animal 字段如果不指定名字默认使用Animal
*Animal //*Animal这个是指针要初始化一下,字段如果不指定名字默认使用Animal
}
type Dog struct {
*Animal
}
func (b *Bird) Fly() {
fmt.Printf("name %s is fly\n", b.Name)
}
func main() {
var b *Bird = &Bird{
Animal: &Animal{}, //初始化Animal
}
b.SetName("bird") //bird继承了Animal类型所以,b就有Animal的方法
b.SetAge(13) //bird继承了Animal类型所以,b就有Animal的方法
b.Fly() //这个 Fly是bird的方法
data, err := json.Marshal(b) //josn序列化
fmt.Printf("marshal result:%s err:%v\n", string(data), err)
var c Bird
err = json.Unmarshal(data, &c) //json序列化
fmt.Printf("c:%#v, err:%v\n", c.Animal, err)
}