1、变量与常量
1.1、变量声明
-
第一种,指定变量类型,如果没有初始化,则变量默认为零值
var num int num = 5
- 第二种,根据值自行判定变量类型
var name = "阿凡达"
- 第三种,省略var,使用:=,:=左边必须是新定义的变量,否则报错
f := 0.0043
- 多变量声明
var a,b,c = 1,2,3 d,e,f := 4,5,6
1.2、常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
- 声明
const PI = 3.14159
- iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
const ( A = iota // iota=0 A=0 B // iota=1 B=1 C // iota=2 C=2 D = "sky" // iota=3 D="sky" E // iota=4 E="sky" F = 39 // iota=5 F=39 G = iota // iota=6 G=6 H // iota=7 H=7 ) const ( J = iota // iota=0 J=0 )
2、流程结构
2.1、if 语句
package main import "fmt" func main() { var num int fmt.Print("请输入 num 的值:") fmt.Scanln(&num) if num >= 5 { fmt.Println("num 大于等于5.") } else if num <= 0 { fmt.Println("num 小于等于0.") } else { fmt.Println("num 大于 0 小于 5.") } }
2.2、switch 语句
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break。
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough 。
语法:
switch var1 { case val1: ... case val2: ... default: ... }
2.3、for 循环
语法
Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。
和 C 语言的 for 一样(1、先执行init,2、再判断 init 是否满足 condition 条件,3、执行循环体,4、执行 post ,给变量增值或减值):
for init; condition; post { 循环体 }
和 C 的 while 一样:
for condition { }
和 C 的 for(;;) 一样:
for { }
EXAMPLE:
//打印九九乘法表
func main() { for i := 1; i <= 9; i++ { for j := 1; j <= i; j++ { fmt.Printf("%d * %d = %d\t", j, i, i*j) } fmt.Println() } }
3、数组
数组是存储一组数据类型相同且长度固定的数据序列。
3.1、声明数组
语法:var variable_name [SIZE] variable_type
var num_array [5]int
3.2、初始化数组
// 定义和赋值放一起 [size]表示数组的长度,[...]表示不指定数组长度,长度由赋值的长度自动推导
var num_array2 = [6]int{0, 1, 2, 3, 4, 5} var string_array = [...]string{"one", "two", "three", "four", "five", "six"}
3.3、访问数组元素
语法:array_name[index]
3.4、数组是值类型
package main /* 1、值类型,赋值的时候,传递的是值的副本 int,float,string,array 2、引用类型,赋值的时候,传递的是内存地址 slice,map 数组的类型:[size]type [6]int [6]int [6]string */ import "fmt" func main() { array1 := [6]int{0, 1, 2, 3, 4, 5} array2 := [6]int{0, 1, 2, 3, 4, 5} array3 := [...]string{"one", "two", "three", "four", "five", "six"} // 数组的类型 fmt.Printf("%T\n", array1) //[6]int fmt.Printf("%T\n", array2) //[6]int fmt.Printf("%T\n", array3) //[6]string // 数组是值类型 array4 := array1 fmt.Println(array1) //[0 1 2 3 4 5] fmt.Println(array4) //[0 1 2 3 4 5] // array1的改变不会影响到array4,说明数组是值类型 array1[0] = 10 fmt.Println(array1) //[10 1 2 3 4 5] fmt.Println(array4) //[0 1 2 3 4 5] // 值类型比较的是值是否一样 fmt.Println(array1 == array2) // false array1[0] = 0 fmt.Println(array1 == array2) // true }
3.5、切片
package main /* slice就是不定长的数组 slice的两种定义方式: 1、 s1 := []int{} []中不填数组的长度,{}中可填数据,也可不填 []type{}中间,则填要存储数据的类型,如 int,string,map[int]string 2、 s2 := make([]int, 0, 8) 通过内置函数make,make专门用来创建引用类型数据 slice的值存储的是内存地址 */ import "fmt" func main() { s1 := []int{} s2 := make([]int, 4, 8) fmt.Println(s1) // [] fmt.Println(s2) // [0 0 0 0] //使用 append 内置函数像 slice 中添加数据 fmt.Printf("s1 的内存地址是:%p;存储的值的内存地址是:%p\n", &s1, s1) s1 = append(s1, 1, 2, 3, 4) fmt.Printf("添加数值后 s1 的内存地址是:%p;存储的值的内存地址是:%p\n", &s1, s1) }
3.6、深浅拷贝
package main /* 1、深拷贝是值类型之间的拷贝,拷贝的是数值 2、浅拷贝是引用类型之间的拷贝,拷贝的是内存地址 copy(dst, src)函数: 相当于 for i:=0;i
4、string
4.1、strings包
package main import ( "fmt" "strings" ) func main() { // string 包的 replace 函数 str1 := "heeelloleeeworld" str1 = strings.Replace(str1, "eee", "www", 1) fmt.Println(str1) // 判断字符串是否包含子字符串 fmt.Println(strings.Contains(str1, "eee")) // 判断字符串中是否包含某个字符 fmt.Println(strings.ContainsAny(str1, "d")) // 判断字符串是否以某个前缀开头 fmt.Println(strings.HasPrefix(str1, "heee")) // 判断字符串是否以某个字符串结尾 fmt.Println(strings.HasSuffix(str1, "rld")) // 以指定字符串切分字符串 fmt.Println(strings.Split(str1, "eee")) }
4.2、strconv包
package main import ( "fmt" "strconv" ) func main() { str1 := "true" b1, _ := strconv.ParseBool(str1) fmt.Printf("%T\n", b1) // Atoi 把 string 转换成 int str2 := "2020" n1,_ := strconv.Atoi(str2) fmt.Printf("%T\n", n1) // n2 := strconv.Itoa(n1) fmt.Printf("%T\n", n2) }
5、函数
5.1、函数的声明
格式:
parameters1和parameters2都是函数形式参数,value1和value2是返回值,
func funName(parameters1 type1, parameters2 type2) (value1 type3, value2 type4) { //函数体 value1 := 4 value2 := 9 return }
5.2、函数的可变参数
格式:
args ...type这里表示的可变参
func funcName([para type], args ...type) { 函数体 }
EXAMPLE:
func Sum(args ...int) { // 求和 sum := 0 for i := 0; i < len(args); i++ { sum += args[i] } fmt.Println(sum) }
5.3、函数的数据类型
我们试着打印下函数的数据类型看看
package main import "fmt" func main() { //注意不带括号,带括号的函数表调用执行 fmt.Printf("fun11 函数的数据类型是:%T\n", fun11) // func() fmt.Printf("fun22 函数的数据类型是:%T\n", fun22) // func(int, int, string) fmt.Printf("fun33 函数的数据类型是:%T\n", fun33) // func([]int) (int, int) // 把函数赋值给一个变量 fun44 := fun11 fun44() // 指向同一块内存地址 fmt.Printf("fun11 函数的内存地址:%p\n", fun11) fmt.Printf("fun44 函数的内存地址:%p\n", fun44) } func fun11() { fmt.Println("this is the test!") } func fun22(n1,n2 int, s1 string) { } func fun33(s1 []int) (int, int) { return 0,0 }
5.4、函数的本质
函数定义时,内存中会开辟一段内存空间给函数用,函数名则指向这段内存空间的地址。
函数名不带括号,就表示这段内存地址;函数名带括号,就表示执行这个函数。
5.5、回调
回调是指,把一个函数当参数,传递给另外一个函数。
package main /* 回调:把一个函数当做参数,传递给另外一个函数 */ import "fmt" func main() { res := opt(1, 2, add) fmt.Println(res) } // 加 func add(a, b int) int { return a + b } //减 func sub(a, b int) int { return a - b } // 算术运算 // 形参名+函数类型 func opt(a, b int, fun func(int, int) int) int { return fun(a, b) }
5.6、闭包
闭包函数:声明在一个函数中的函数
闭包:闭包函数总能访问外部函数的变量,外部函数的变量不会因调用而销毁
package main import "fmt" func main() { zhaoyun := walk("赵云") zhangfei := walk("张飞") zhaoyun(2) zhangfei(3) zhangfei(1) zhaoyun(2) } func walk(name string) func(int) { total := 0 haha := func(hour int) { total += hour fmt.Printf("%s: 行军%d小时!\n", name, hour) fmt.Printf("%s: 一共行军%d小时!\n", name, total) } return haha }
6、指针
一个指针变量指向了一个值的内存地址。
*表示去指针数据
&表示取地址
定义:
// 定义一个存储整数类型的指针 var p1 *int // 定义一个双重指针 var p2 **int
使用:
// 给指针赋值 p1 = &a p2 = &p1
// 取出指针变量的值
*p1
*p2
空指针:
空指针用nil表示
7、结构体
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
定义:
type struct_variable_type struct { member definition member definition ... member definition }
example:
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { // 创建一个新的结构体 fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407}) // 也可以使用 key => value 格式 fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407}) // 忽略的字段为 0 或 空 fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"}) }
访问结构体成员:
如果要访问结构体成员,需要使用点号 . 操作符
结构体.成员名