Go(二)函数
自定义类型
两种用户定义的类型
- 结构类型
- 基于一个已有的类型,将其作为新类型的类型说明
结构体变量定义和初始化
type struct_variable_type struct {
member definition
member definition
...
member definition
}
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
// 或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
实例
package main import "fmt" type Person struct {
name string
sex byte
age int
} func main() { // 顺序初始化,必须全部初始化完整
var person Person = Person{"wang", 'f', }
fmt.Println(person) // 部分初始化
person1 := Person{name: "zhao", sex: 'm'}
fmt.Println(person1.name)
}
赋值、比较和传参
使用.索引成员变量
// 部分初始化
person1 := Person{name: "zhao", sex: 'm'}
fmt.Println(person1.name) person1.name = "li"
fmt.Println(person1.name)
比较
只能使用 == 和 !=,不能使用 > < >= <=
// 结构体比较
person2 := Person{name: "zhao", sex: 'm', age: }
person3 := Person{name: "zhao", sex: 'm', age: }
person4 := Person{name: "zhao", sex: 'm', age: }
fmt.Println(person2 == person3) // true
fmt.Println(person3 == person4) // false
相同类型的结构体可以进行赋值
相同类型结构体:成员变量的类型、个数、顺序一致
var tmp Person
tmp = person1
fmt.Println(tmp.name)
因此函数体内部可以使用结构体传参,因为实参可以赋值给相同结构体类型的形参,值传递。几乎不用,内存消耗大,效率低。
func test(person Person) {
println(person.name)
} func main() { var temp Person
test(temp) }
结构体指针
结构体指针变量定义和初始化
1.顺序初始化和部分初始化
var man *Person = &Person{"zhao", 'm', }
fmt.Println(man.name)
var man1 *Person = &Person{name: "zhao", sex: 'm'}
fmt.Println(man1.name)
2.使用new
var man2 *Person = new(Person);
man2.name = "zhao"
man2.sex =
man2.age =
使用.指针索引成员变量
结构体变量的地址就是结构体首个元素的地址
fmt.Printf("&tmp = %p \n", &tmp)
fmt.Printf("&tmp.name = %p \n", &tmp.name)
结果
&tmp = 0xc000004500
&tmp.name = 0xc000004500
结构体指针的值就是结构体首个元素的地址
fmt.Printf("man2 = %p\n", man2)
fmt.Printf("&man2.name = %p\n", &man2.name)
结果
man2 = 0xc00008e080
&man2.name = 0xc00008e080
结构体指针作为函数参数
import "fmt" type Person struct {
name string
sex byte
age int
} func test1(person * Person) {
person.name = "wang"
} func main() { fmt.Println("man2:", man2)
test1(man2)
fmt.Println("man2", man2) }
结果
man2: &{zhao }
man2 &{wang }
发现通过指针变量可以修改结构体,传引用,使用频率高
也是实参拷贝值给形参,不过这次拷贝的是地址值
或
fmt.Println(person1.name)
test1(&person1)
fmt.Println(person1.name)
结果
li
wang
函数是一等公民
与其他主要编程语言的差异
1.可以有多个返回值
2.所有参数都是值传递
slice、map、channel会有传引用是错觉,如切片背后是数组,是一个数据结构,里面包含了指向对应数组的指针,数据结构被复制,指针操作的仍是同一块空间,感觉像是传引用
3.函数可以作为变量的值
4.函数可以作为参数和返回值
package fun_test import (
"fmt"
"math/rand"
"testing"
"time"
) // 多个返回值
func returnMultiValues()(int, int) {
return rand.Intn(), rand.Intn()
} // 函数可以作为参数和返回值
// 计算inner函数运行的时间
func timeSpent(inner func(op int)int) func(opt int) int {
return func(n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent:", time.Since(start).Seconds())
return ret
}
} func slowFun(op int)int{
time.Sleep(time.Second*)
return op
} func TestFn(t *testing.T){
a, _ := returnMultiValues()
t.Log(a)
tsSF := timeSpent(slowFun)
t.Log(tsSF())
}
结果:
=== RUN TestFn
time spent: 1.0000582
--- PASS: TestFn (1.00s)
func_test.go:32: 1
func_test.go:34: 10
PASS
可变参数及defer
可变参数会被转换为数组,通过数组变量来完成
func sum(ops ...int) int {
s :=
for _, op := range ops{
s += op
}
return s
} func TestParam(t *testing.T) {
s := sum(, , , , )
fmt.Println(s)
}
=== RUN TestParam
15
--- PASS: TestParam (0.00s)
PASS
defer
func clear() {
fmt.Println("clear resources")
} func TestDefer(t *testing.T) {
defer clear()
fmt.Println("Start")
panic("Fatal error") //defer仍会执行
println("Stop")
}
=== RUN TestDefer
Start
clear resources
--- FAIL: TestDefer (0.00s)
panic: Fatal error [recovered]
panic: Fatal error
会发现出现了异常,clear()依然会执行,
异常之前的fmt.Println("Start")被执行
异常之后的fmt.Println("Stop")没有被执行
最新文章
- JavaScript(四) Window窗体操作
- 【转】PowerShell入门(十二):编写PowerShell管理单元和二进制模块
- codeforces 496B. Secret Combination 解题报告
- js类(继承)(一)
- reactnativemodal
- Java的位运算符—— 与(&;)、非(~)、或(|)、异或(^)
- POJ1035——Spell checker(字符串处理)
- NOIP2004 合并石子
- C# const和statci readonly区别
- Android中获取电池电量
- AJAX技术之网易滚动新闻的简单实现(附源码)--AJAX
- 【NOIP2012】 疫情控制
- Android流媒体开发之路二:NDK开发Android端RTMP直播推流程序
- bash: lspci: command not found解决方法
- js三元表达式
- Exp3 免杀原理和实践
- 走进JDK(十二)------TreeMap
- ajax传输中文参数乱码,本地使用tomcat不乱码,liunx+weblogic乱码
- [No0000165]SQL 优化
- RN animated组动画
热门文章
- js中给数组添加元素的方法有哪些
- Yii2 $app总结
- sql 2008常用语法语句收集
- 「树的直径」BFS方法证明
- S1.2 Python开发规范指南
- BZOJ 2281: [Sdoi2011]黑白棋(dp+博弈论)
- window安装nodejs
- [TensorFlow 2] [Keras] fit()、fit_generator() 和 train_on_batch() 分析与应用
- GPIO 的 8 种工作模式
- UI:UI 目录