1.hello world
学习编程的第一件事就是输出**hello world** 。^-^
package main
import "fmt"
func main(){//大括号位置固定
fmt.Println("hello world")
}
2.变量
Go语言数据类型:(1)布尔型:bool (2) 数字类型:整型 int 和浮点型 float32、float64 (3) 字符串类型:string (4) 派生类型:a. 指针类型(Pointer)b.数组类型 c.结构化类型(struct) d.Channel 类型 e.函数类型 f.切片类型 g.接口类型(interface) h.Map 类型。
var是声明的关键字,声明变量有两个方式:(1)var name int = 10 (2)name := 10,类型要在变量名后。
多个变量声明:(1)var name1, name2 int = 20, 30 或 var name1, name2 = 20, "hello" (2) name1, name2 := 10, "hello" 。
go语言中字符串是内置类型,可以用 + 拼接:name := "hello" + "world" 。
数字类型转换:var name1 float64 = 1.11415365949 name2 := int( name1 )
如果变量没有初始化,则默认为零值:(1) 布尔类型: false (2) 数字类型: 0 (3) 字符串类型: 空字符串 ( "" ) (4) 其他类型:nil 。
golang 的常量没有确定的类型,能够根据使用的上下文自动确定类型: const name1, name2 = 10, "hello" 。
golang中声明的局部变量必须在相同的代码块中使用它,全局变量是允许声明但不使用。
3.if-else
if后面没有括号,但可以在条件面前进行一些操作,换言之,if语句可以在条件表达式前执行一个简单的语句。
package main
import "fmt"
func main() {
if name := 10; name > 10 { //if-else括号位置固定
fmt.Println("name > 10")
} else {
fmt.Println("name < 10")
}
}
4.循环
go只有一种循环:for循环。去掉分号后,和while作用相同。
break: 中断循环 continue: 跳过当前循环,进入下一循环 goto: 转移到被标记的位置。
for 条件的起始值 ;循环条件;控制自变量改变
package main
import "fmt"
func main() {
for i := 0; i <= 10; i++ {
fmt.Println(i)
}
name := 5
for name < 10 {
fmt.Println(name)
name++
}
}
5.switch
Go语言中switch语句的case 自带 break 语句,匹配成功时停止。如果需要执行后面的 case,使用 fallthrough 。switch 的 case 后可以不为常量,为其他判断语句。因此Go语言中switch更为强大。
switch语句也可以在条件表达式前执行一个简单的语句。
switch不附加条件时 等价switch true 。
package main
import "fmt"
func main() {
switch name := "hello"; name {
case "ni hao":
fmt.Println("ni hao")
case "hello":
fmt.Println("hello")
default:
fmt.Println("bye")
}
}
6.数组
定义数组:将变量 a 声明为拥有 n 个整数的数组: var a = [n]int
初始化数组:(1) var a = [4]int{1,2,3,4} (2) a := [4]int{1,2,3,4}
注意:数组长度不可变,切片长度可变。
package main
import "fmt"
func main() {
var a = [4]int{1, 2, 3, 4}
fmt.Println(a[1])//2
b := [4]int{1, 2, 3, 4}
fmt.Println(b)//[1 2 3 4]
var c [4]int
c[1] = 9
fmt.Println(c[1]) //9
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i ][j] = i + j
}
}
fmt.Println("2d:", twoD)//2d: [[0 1 2] [1 2 3]]
}
7.切片
切片不存储任何数据,它只是描述了底层数组中的一段。更改切片的元素会修改其底层数组中对应的元素。
创建切片:(1) var a []int (2) a := make([]int, len, cap) (3) var a []int = make([]int, len, cap)
(len为切片长度,cap为切片容量(若不指定容量可省略)。切片的长度就是它所包含的元素个数。切片的容量是从它的第一个元素到其底层数组元素末尾的个数。)
初始化切片:(1) a := []int {1,2,3 } (2) a := 数组名[下标:上标] (切片下标的默认值为 0,上标的默认值切片的长度)。
切片的使用:var a []int = 数组名[1:4] (切片包括第一个元素,排除最后一个元素,该切片a包含 数组 中下标从 1 到 3 的元素)
len(a) 获取切片长度,cap(a) 获取切片容量。
切片的零值是 nil。nil 切片的长度和容量为 0 且没有底层数组。
切片可用append追加元素,需要赋值回原切片:a = append(a, "world") 。
可以将一个切片的数值拷贝到另一个切片:copy(b,a) (将切片a的数值拷贝到切片b上)。
package main
import "fmt"
func main() {
s := make([]string, 3) //用make创建切片
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2]) //c
fmt.Println("len", len(s)) //3
s = append(s, "d") //切片可用append追加元素,需要赋值回原切片
s = append(s, "e", "f")
fmt.Println(s) //[a b c d e f]
c := make([]string, len(s)) //创建切片对应的长度
copy(c, s) //拷贝数值
fmt.Println(c) //[a b c d e f]
fmt.Println(s[2:5]) //[c d e]
fmt.Println(s[:5]) //[a b c d e]
fmt.Println(s[2:]) //[c d e f]
good := []string{"gc", "o", "o", "d"}
fmt.Println(good) //[g o o d]
}
8.map(映射)
创建map:(1)name := make(map[string]int) 用make创建空map,[ ] 内是key类型,[ ] 外右侧是value类型
(2) name := map[string]int{"one": 1, "two": 2} 用 := 赋值创建
(3) var name = map[string]int{"one": 1, "two": 2} 用var声明变量创建
在map中的操作:(1) 插入或修改元素:name[key] = value (2) 删除元素:delete (name, key)
通过双赋值检测某个key值是否存在:a,ok = name[key] ,若映射name中存在key值,ok为true,a为value值;否则 ok为false,a为0。
package main
import "fmt"
func main() {
m := make(map[string]int) //1.用make创建空map,[]内是key类型,[]外是value类型
m["one"] = 1
m["two"] = 2
fmt.Println(m) //map[one:1 two:2]
fmt.Println(len(m)) //2
fmt.Println(m["one"]) //1
fmt.Println(m["unknow"]) //0
r, ok := m["unknow"] //ok判断map内是否有key存在
fmt.Println(r, ok) //0 false
delete(m, "one") //删除
fmt.Println(m) //map[two:2]
m2 := map[string]int{"one": 1, "two": 2} //2.用:=创建
var m3 = map[string]int{"one": 1, "two": 2} //3。用var创建
fmt.Println(m2, m3)
}
9.range
for 循环的 range 形式可遍历切片或映:for i, j := range name。
(1) 当使用 for 循环遍历切片时,每次迭代都会返回两个值。第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本。
若只需要下标或元素值,可用将值赋予 _ :(1) for i, _ := range name,(2) for _, j := range name
若只需要下表,可直接省略第二个变量:for i := range name
(2) 当使用 for 循环遍历映射时,每次迭代都会返回两个值。第一个值为key值,第二个值为value值。
package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums { //range对数组快速遍历返回两个值
sum += num
if num == 2 { //第一个值是索引,第二个值是对应位置的值
fmt.Println("index: ", i, "num: ", num) //index: 0 num: 2
}
}
fmt.Println(sum) //9
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m { //第一个值是key,第二个值是value
fmt.Println(k, v) //
}
for k := range m {
fmt.Println("key", k)
}
}
10.函数
Go语言函数格式:func name( 参数列表 ) 函数返回值类型
可以返回多个结果和错误信息:value, ok := name( 参数列表 ) ,value为返回值,若信息正确,ok为true,否则ok为false。
Go语言中,方法是一类带特殊的 接收者 参数的函数。方法接收者在自身的参数列表内,位于 func 关键字和方法名(相当于函数名)之间:func (接受者的名字 数据类型) name( 参数列表 ) 方法返回值类型,通过m.name( 参数 )来调用 ,这是和函数不同的地方 (m是以接收者数据类型命名的变量)。
11.指针
Go语言中的指针相对简单,取止符仍是&,指针的零值为 nil 。
指针的声明:var a *int。
可以用指针来传入参数:func 函数名(a, b *int) int,这样可以直接更改传入的变量的值。
12.结构体
结构体是带类型的字段的集合,结构体格式:type name struct。
结构体的初始化:(1) 用结构体的名称初始化结构体变量,传入每个字段的初始值 (2) 直接传入每个字段的初始值 (3) 可以只指定一部分的值初始化 (4) 未初始化的值,则自动初始化为空值,数字为0,字符串为空字符串 。
package main
import "fmt"
// 结构体是带类型的字段的集合
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "1024"} //1.用结构体的名称初始化结构体变量,传入每个字段的初始值
b := user{"wang", "1024"}//2.
c := user{name: "wang"} //3.可以只指定一部分的值
c.password = "1024"
var d user //4.未初始化,则自动初始化为空值,数字为0,字符串为空字符串
d.name = "wang" //可以读取和写入字符串内容
d.password = "1024"
fmt.Println(a, b, c, d) //{wang 1024} {wang 1024} {wang 1024} {wang 1024}
fmt.Println(checkPassword(a, "haha")) //false
fmt.Println(checkPassword2(&a, "haha")) //false
}
func checkPassword(u user, password string) bool { //结构体可作为函数的参数
return u.password == password
}
func checkPassword2(u *user, password string) bool { //用指针可以修改结构体
return u.password == password
}
13.结构体方法
可以为结构体类型定义方法,数据类型为声明的结构体名字。
package main
import "fmt"
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) { //用指针对结构体进行修改
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) //true
}
14.错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func finduser(users []user, name string) (v *user, err error) { //error说明这个函数可能返回错误
//用简单的if-else处理错误
for _, u := range users {
if u.name == name {
return &u, nil //没有错误出现,返回两个值,原本的结果和nil值
}
}
return nil, errors.New("not found") //有错误出现
}
func main() {
u, err := finduser([]user{{"wang", "1024"}}, "wang") //调用返回错误的函数,接收需2个变量
if err != nil { //判断错误是否存在
fmt.Println(err)
return
}
fmt.Println(u.name) //wang
if u, err := finduser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
15.字符串操作
a := "hello"
(1) 判断一个字符串内是否包含另一个字符串:strings.Contains(a, "hello") ,在a中查找是否有hello,返回true或false。
(2)字符串计数:strings.Count(a, "hello") ,在a中查找有几个hello,返回整型数据。
(3)前缀判断:strings.HasPrefix(a, "he") ,判断a中是否有he作为前缀,返回true或false。
(4)后缀判断:strings.HasSuffix(a, "llo") ,判断a中是否有llo作为后缀,返回true或false。
(5)查找某个字符串的位置:strings.Index(a, "ll") ,返回ll的位置。
(6)连接多个字符串:strings.Join([]string{"he", "llo"}, "-") ,用**-**将he和llo拼接。
(7)重复多个字符串:strings.Repeat(a, 2) ,将a复制两次实现。
(8)替换字符串中的字符:strings.Replace(a, "e", "E", -1) ,将a中的e替换成E。
(9)指定字符分割字符串:strings.Split("-a-b-c", "-") ,-起分割作用,输出a b c。
(10)将字符串转换成小写形式:strings.ToLower(a) 。
(11)将字符串转换成大写形式:strings.ToUpper(a) 。
(12)统计字符串的长度:len(a) 。中文的单位长度为3。
(13)去除字符串的首位空白:strings.TrimSpace(a) 。