本篇内容:基本类型、流程控制、函数、包引用
基本类型
package main
import "fmt"
func main() {
// 布尔类型
var flag1 bool // bool布尔类型默认值为false
fmt.Println(flag1)
flag2 := true // 默认推导类型
fmt.Println(flag2)
// 复数类型
com1 := complex(1, 2) // 1 + 2i
fmt.Println(real(com1), imag(com1)) // 打印实部和虚部: 1, 2
}
类型转换
只能发生在两种类型相互兼容的情况下;
需要显式地声明。
// 类型转换(两种类型相互兼容)
var ch1 byte = 'a'
// var i1 int = ch1 // 错误!类型转换需要显式声明
var i1 int = int(ch1) // 显式声明
fmt.Println(ch1)
fmt.Println(i1) // 97
类型别名
type 别名 类型
// 类型别名
type myint64 int64 // type 别名 类型
var i2 myint64 = 1
fmt.Println(i2)
定义多个类型别名
// 定义多个类型别名
type (
myint int
mystring string
)
流程控制
选择结构
if else
// if else
if a := 3; a == 3 { // if支持一个初始化表达式,和条件表达式用分号隔开
fmt.Println(true)
} else {
fmt.Println(false)
}
switch
// switch
switch i1 := 10; i1 { // 初始化表达式;变量
case 10:
fmt.Println(true) // 默认自带break关键字
default:
fmt.Println(false)
}
switch特殊之处
// 特殊之处
i2 := 3
switch { // 这里可以不写判断条件
case i2 > 3: // 这里可以写判断条件
fmt.Println(false)
default:
fmt.Println(true)
}
循环结构
for
// for
for i := 0; i < 10; i++ { // 初始化条件;控制条件;变化条件(初始化条件只执行一次)
fmt.Println(i)
}
range迭代器
// range迭代器
str := "str"
for index, item := range str { // range两个返回值: 下标, 元素
fmt.Printf("%d %c\n", index, item)
}
for _, item := range str { // 匿名变量: 丢弃下标不处理
fmt.Printf("%c\n", item)
}
break和continue
和Java用法一样
函数
普通函数
func 函数名 (参数) (返回) {}
package main
import "fmt"
// 无参数无返回函数
func func1() {
fmt.Println("func1")
}
// 有参数无返回函数
func func2(i1 int, str1 string) { // 固定参数(必传)
fmt.Printf("i1 = %d, str1 = %v\n", i1, str1) // %v使用默认格式输出
}
func func3(arr ...int) { // 不定参数(可以传0个或多个),arr为参数数组
for _, item := range arr { // range迭代器
fmt.Println(item)
}
}
func func4(i1 int, arr ...int) { // 同时存在固定和不定参数,不定参数一定要位于形参的末尾
fmt.Println("i1 = ", i1)
for _, item := range arr { // range迭代器
fmt.Println(item)
}
}
// 无参数有返回函数
func func5() (r1 int) { // 一个返回值
// return 1
// 或者
r1 = 1
return
}
func func6() (r1 int, r2 string) { // 多个返回参数
r1 = 1
r2 = "hello"
return
}
// 有参数有返回函数
func func7(i1 int, i2 int) (big int, small int) {
big, small = i1, i2
if i2 > i1 {
big, small = small, big
}
return
}
func main() {
// func1()
// func2(1, "hello")
// func3() // 传0个
// func3(1, 2, 3) // 传3个
// func4(1, 2)
// i5 := func5()
// fmt.Println(i5)
// i6, str6 := func6()
// fmt.Println(i6, str6)
big, small := func7(2, 10)
fmt.Printf("big = %d, small = %d\n", big, small)
}
递归函数
使用递归函数计算1-10累加
func digui(i int) int {
if i == 1 {
return i
}
return i + digui(i-1)
}
func main() {
// func1()
// func2(1, "hello")
// func3() // 传0个
// func3(1, 2, 3) // 传3个
// func4(1, 2)
// i5 := func5()
// fmt.Println(i5)
// i6, str6 := func6()
// fmt.Println(i6, str6)
// big, small := func7(2, 10)
// fmt.Printf("big = %d, small = %d\n", big, small)
sum := digui(10)
fmt.Println(sum)
}
函数类型
具有相同参数和相同返回的函数为同一种类型
非常类似于方法的重载
type funcType func(参数) (返回)
package main
import "fmt"
func func1(i1 int, i2 int) (result int) { // i1 + i2
result = i1 + i2
return
}
func func2(i1 int, i2 int) (result int) { // i1 - i2
result = i1 - i2
return
}
// 定义函数类型(这类函数为计算类型函数)
type funcCalc func(int, int) int
func main() {
var calc funcCalc = func1 // 加法
result := calc(2, 1) // 3
fmt.Println(result)
calc = func2 // 减法(多态的体现)
result = calc(2, 1) // 1
fmt.Println(result)
}
回调函数(参数类型包含函数类型的函数)
package main
import "fmt"
func func1(i1 int, i2 int) (result int) { // i1 + i2
result = i1 + i2
return
}
func func2(i1 int, i2 int) (result int) { // i1 - i2
result = i1 - i2
return
}
// 定义函数类型(这类函数为计算类型函数)
type funcCalc func(int, int) int
// 回调函数
func func3(i1 int, i2 int, calc funcCalc) (result int) {
result = calc(i1, i2)
return
}
func main() {
result := func3(2, 1, func1)
fmt.Println(result) // 3
result = func3(2, 1, func2)
fmt.Println(result) // 1
}
匿名函数
匿名函数声明1
package main
import "fmt"
func main() {
i1 := 1
str1 := "hello"
// 匿名函数声明方式1
f1 := func() { // 用变量接收匿名函数!!!
fmt.Printf("i1 = %d, str1 = %v\n", i1, str1) // 匿名函数捕获外部变量
}
// 匿名函数调用
f1()
// 或这样调用
type funcType func() // 无参数无返回类型
var f2 funcType = f1
f2()
}
匿名函数声明2
package main
import "fmt"
func main() {
i1 := 1
str1 := "hello"
// 表示声明并调用
result := func() int { // 用变量接收返回!!!
fmt.Printf("i1 = %d, str1 = %v\n", i1, str1)
return 1
}()
fmt.Println(result)
// 带参数的匿名函数声明并调用
func(param1 int, param2 string) {
fmt.Printf("param1 = %d, param2 = %v\n", param1, param2)
}(i1, str1)
}
闭包
匿名函数捕获外部变量形成闭包
(只要闭包存在,即使捕获的变量超出了作用域也不会被销毁)
package main
import "fmt"
func square() func() int { // 这里"func() int"是一个整体,表示square()函数的返回结果是一个匿名函数
var x int // 默认值为0
return func() int {
x++ // 闭包
return x * x
}
}
func main() {
f := square() // f为square()返回的匿名函数
// 即使square()结束后,x也会隐式地存在于f中
fmt.Println(f()) // 1
fmt.Println(f()) // 4
fmt.Println(f()) // 9
fmt.Println(f()) // 16
}
defer延迟执行
会在函数结束前调用
有点像Java里try-catch-finally中finally块的逻辑
package main
import "fmt"
func main() {
defer fmt.Println("11") // main结束前执行
fmt.Println("44") // 在"11"之前输出
// 多个defer,最先定义的最后执行
defer fmt.Println("22")
defer fmt.Println("33")
}
defer延迟调用匿名函数
匿名函数是延迟调用的,但是传参的动作却不是延迟的!
package main
import "fmt"
func main() {
// 初始化
i := 1
defer func(i int) { // 匿名函数闭包
fmt.Println(i)
}(i) // 匿名函数是延迟调用的,但是传参的动作却不是延迟的!!!
// 赋值
i = 10
fmt.Println(i)
}
输出结果
作用域
局部变量
在函数内声明的变量,作用域只在当前函数内
全局变量
在函数外声明的变量,作用域在整个包
工程
一个工程只能有一个main入口,main入口必须在main包内
go代码文件必须放在src目录下
同一个目录下的文件包名必须相同
例如package xxx
import
如果要调用非当前目录的其它文件,需要先import
单个调用
import "fmt"
多个调用
import (
"fmt"
"os"
)
调用但是不使用,可以执行对应包的init()函数
import _ "fmt"
.操作
作用是在调用这个包的成员时,可以省略包名,直接".成员"调用
import . "fmt"
别名操作
作用是在调用这个包的成员时,可以通过"别名.成员"调用
import f "fmt"
不当之处,请予指正。