Technique/Tips
defer的使用—推迟到最后执行
package main
import "fmt"
func func1() {
fmt.Println("A")
}
func func2() {
fmt.Println("B")
}
func func3() {
fmt.Println("C")
}
func deferFunc() int {
fmt.Println("defer func called")
return 0
}
func returnFunc() int {
fmt.Println("return func called")
return 0
}
func returnAndDefer() int {
defer deferFunc()
return returnFunc()
}
func main() {
//defer放在最后打印,压栈顺序导致先打印end2,再打印end1
defer fmt.Println("main end1")
defer fmt.Println("main end2")
fmt.Println("main:hello go1")
fmt.Println("main:hello go2")
//打印结果倒序,因为压栈
defer func1()
defer func2()
defer func3()
//看defer和return哪个先打印,先打印return,后打印defer
returnAndDefer()
}
数组值传递
package main
import "fmt"
//传递数组,传的是值,只改动涉及的几个元素
func printArray(myArray [4]int) {
for index, value := range myArray {
fmt.Println("index=", index, "value=", value)
}
}
func main() {
//固定长度的数组,初始化默认每位是0
var myArray [10]int
myArray2 := [10]int{1, 2, 3, 4}
myArray3 := [4]int{11, 22, 33, 44}
//= 是赋值, := 是声明变量并赋值,系统自动推断类型,不需要关键字
for i := 0; i < len(myArray); i++ {
fmt.Println(myArray[i])
}
for index, value := range myArray2 {
fmt.Println("index=", index, "value=", value)
}
//查看数据类型,不知道为什么打印不出来
fmt.Println("myArray types = %T\n", myArray)
fmt.Println("myArray2 types = %T\n", myArray2)
fmt.Println("myArray3 types = %T\n", myArray3)
//打印传递的数组
printArray(myArray3)
}
动态数组引用传递
package main
import "fmt"
func printArray(myArray []int) {
//引用传递
//_,表示匿名的变量,之后不会用到名字
for _, value := range myArray {
fmt.Println("value=", value)
}
myArray[0] = 100
}
func main() {
myArray := []int{1, 2, 3, 4} //动态数组,[]内没有长度,切片slice
fmt.Printf("myArray type is %T\n", myArray)
printArray(myArray)
fmt.Println("------")
for _, value := range myArray {
fmt.Println("value=", value)
}
}
四种切片声明方式
package main
import "fmt"
//四种slice切片方式
func main() {
//方法一
//slice1 := []int{1, 2, 3}
//方法二:开辟三个空间,默认值是0
var slice1 []int
//slice1 = make([]int, 3)
//方法三
//var slice1 []int = make([]int, 3)
//方法四: :=推断出slice是切片
//slice1 := make([]int, 3)
//slice1[0] = 100
fmt.Println("len=%d, slice1=%v\n", len(slice1), slice1)
//判断slice是否为空切片
if slice1 != nil {
fmt.Println("slice是有空间的")
} else {
fmt.Println("slice是空切片")
}
}
slice切片追加与截取
package main
import "fmt"
func main() {
var numbers = make([]int, 3, 5)
fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
//追加元素,看容量的变化
// 【0,0,0,1】 cap=5
numbers = append(numbers, 1)
// 【0,0,0,1,2】 cap=5
numbers = append(numbers, 2)
// 【0,0,0,1,2,3】 cap=10
numbers = append(numbers, 3)
fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
fmt.Println("------------")
var numbers2 = make([]int, 3)
numbers2 = append(numbers2, 2)
fmt.Println("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
//数组拷贝
s := []int{1, 2, 3} // [1,2,3]
s1 := s[0:2] //[1,2]
fmt.Println(s1)
s1[0] = 100
fmt.Println(s)
fmt.Println(s1)
s2 := make([]int, 3) //[0,0,0]
//s2复制了s
copy(s2, s)
fmt.Println(s2)
}
map的三种声明定义方式
package main
import "fmt"
func main() {
//声明是一种map类型,key是string,value是string
var myMap1 map[string]string
if myMap1 == nil {
fmt.Println("myMap是一个空map")
}
//在使用map前,先用make分配空间
myMap1 = make(map[string]string, 10)
myMap1["one"] = "java"
myMap1["two"] = "C++"
myMap1["three"] = "python"
fmt.Println(myMap1)
//第二种声明方式
myMap2 := make(map[int]string)
myMap2[1] = "java"
myMap2[2] = "C++"
myMap2[3] = "python"
fmt.Println(myMap2)
//第三种声明方式
myMap3 := map[string]string{
"one": "php",
"two": "c++",
"three": "python",
}
fmt.Println(myMap3)
}
占位符 |
说明 |
举例 |
输出 |
%v |
相应值的默认格式。 |
Printf(“%v”, people) |
{zhangsan} |
%T |
相应值的类型的Go语法表示 |
Printf(“%T”, people) |
main.Human |
|
%d |
十进制表示 |
Printf(“%d”, 0x12) |
18 |
|
Struct的使用
package main
import "fmt"
//给int起了一个别名
type myint int
//定义一个结构体,把多种数据类型放在一起,书有两种属性,书名和作者
type Book struct {
title string
auth string
}
func changeBook(book Book) {
book.auth = "666"
}
//指针传递
func changeBook2(book *Book) {
book.auth = ""
}
func main() {
var a myint = 10
fmt.Println("a=", a)
//%d表示十进制,%T表示main.Human
fmt.Printf("type of a =%T\n", a)
var book1 Book
book1.title = "Golang"
book1.auth = "zhang3"
fmt.Println("%v\n", book1)
changeBook(book1)
fmt.Println("%v\n", book1)
//传book1的地址
changeBook2(&book1)
fmt.Println("%v\n", book1)
}
Go的继承
package main
import "fmt"
type Human struct {
name string
sex string
}
func (this *Human) Eat() {
fmt.Println("Human.eat...")
}
func (this *Human) Walk() {
fmt.Println("Human.walk...")
}
//-------------------------------------
type Superman struct {
Human //表示继承Human类的方法
level int
}
//重定义父类的方法
func (this *Superman) Eat() {
fmt.Println("Superman...")
}
//定义子类的新方法
func (this *Superman) Fly() {
fmt.Println("Superman.fly()...")
}
func (this *Superman) Print() {
fmt.Println("name=", this.name)
fmt.Println("sex=", this.sex)
fmt.Println("level=", this.level)
}
func main() {
h := Human{"zhang3", "female"}
h.Eat()
h.Walk()
//定义一个子类对象
//方法一:s := Superman{Human{"li4", "female"}, 88}
//方法二:
var s Superman
s.name = "Li4"
s.sex = "male"
s.level = 88
s.Walk() //调用父类的方法
s.Eat() //调用子类的方法,子类重写了
s.Fly() //待用子类的方法
s.Print()
}
多态
package main
import (
"fmt"
)
//多态的要素
//有一个父类(有接口) ,interface接口的本质是一个指针
type AnimalIF interface {
Sleep()
GetColor() string //获取动物的颜色
GetType() string //获取动物的种类
}
//具体的子类,实现了父类的所有接口方法
type Cat struct {
color string //猫的颜色
}
//子类cat完全实现一个接口
func (this *Cat) Sleep() {
fmt.Println("Cat is sleep")
}
func (this *Cat) GetColor() string {
return this.color
}
func (this *Cat) GetType() string {
return "Cat"
}
//具体的类
type Dog struct {
color string //猫的颜色
}
//子类dog完全实现一个接口
func (this *Dog) Sleep() {
fmt.Println("Cat is sleep")
}
func (this *Dog) GetColor() string {
return this.color
}
func (this *Dog) GetType() string {
return "Dog"
}
func showAnimal(animal AnimalIF) {
animal.Sleep() //多态
fmt.Println("color=", animal.GetColor())
fmt.Println("kind=", animal.GetType())
}
func main() {
//父类类型的变量(指针)指向(引用)子类的具体数据变量
/* var animal AnimalIF //接口的数据类型,父类指针
animal = &Cat("Green")
animal.Sleep() //调用cat的sleep方法,多态现象
animal = &Dog("Yellow")
animal.Sleep() //调用dog的sleep方法,多态现象
*/
cat := Cat{"Green"}
dog := Dog{"Yellow"}
showAnimal(&cat)
showAnimal(&dog)
}
Share
腾讯云技术实践精选集2021