Go(一):Go基础语法入门
Go基础语法入门
第一个go程序
go.mod
module go-appgo 1.20
user/user.go
package user// Hello 首字母大写为公共方法 func Hello() string {return "Hello" }
main.go
package mainimport ("fmt""go-app/user" )func main() {str := user.Hello()fmt.Println(str) }
变量
声明的变量必须使用,否则报错异常
package mainimport ("fmt"
)func funA() (string, int) {// 匿名变量return "Lee", 12
}func main() {// 变量初始化var name string = "123"fmt.Println(name) // 123// 批量变量初始化var (realName string = "Lee"age int = 24sex string = "难~")fmt.Printf("%v ---> %v ---> %v \\n", realName, age, sex) // Lee ---> 24 ---> 难~// 类型推断var say = "Hello"fmt.Println(say) // Hello// 批量初始化var a, b, c = 1, 2, 3fmt.Printf("%v ---> %v ---> %v \\n", a, b, c) // 1 ---> 2 ---> 3// (短变量声明)只能应用于函数内部x := 4y := 5z := 6fmt.Printf("%v ---> %v ---> %v \\n", x, y, z) // 4 ---> 5 ---> 6// 匿名变量str, num := funA()fmt.Println(str, num) // Lee 12
}
常量
基本常量
const HELLO = "Hello Lee!!!"
iota
从0开始,每次调用自动加1const (count1 = iotacount2 = iotacount3 = iota ) fmt.Println(count1, count2, count3) // 0 1 2
_
跳过const (count1 = iota_count3 = iota ) fmt.Println(count1, count3) // 0 2
中间插值
等价于跳过const (count1 = iotacount2 = 100count3 = iota ) fmt.Println(count1, count2, count3) // 0 100 2
数据类型
package mainimport "fmt"func i() string {return "I"
}func main() {var a = "Lee"var b = 18var c = true // 注意:不允许用0或1来表示false或truevar d = 12.5var e = &d // 取d的地址(指针类型)var f = [...]int{1, 2, 3} // [...] 省略长度var g = []int{1, 2, 3} // 动态数组var h = [4]int{1, 2, 3} // 固定长度数组var j = `<html><body>Hello Lee</body></html>` // 字符串字面量,可换行fmt.Printf("%T \\n", a) // stringfmt.Printf("%T \\n", b) // intfmt.Printf("%T \\n", c) // boolfmt.Printf("%T \\n", d) // float64fmt.Printf("%T \\n", e) // *float64fmt.Printf("%T \\n", f) // [3]intfmt.Printf("%T \\n", g) // []intfmt.Printf("%T \\n", h) // [4]intfmt.Printf("%T \\n", i) // func() stringfmt.Printf("%T \\n", nil) // <nil>fmt.Printf("%v \\n", j) // 字符串...}
字符串处理
package mainimport ("bytes""fmt""strings"
)func main() {// 字符串拼接a := "Hello"b := "Lee"msg1 := fmt.Sprintf("%s %s!!!", a, b)fmt.Println(msg1) // Hello Lee!!!msg2 := strings.Join([]string{a, b}, "-")fmt.Println(msg2) // Hello-Leevar buffer bytes.Bufferbuffer.WriteString("Hello ")buffer.WriteString("Lee")fmt.Println(buffer.String()) // Hello Lee// 字符串切片msg3 := "Hello Lee, My name is WangDeFa!!!"fmt.Println(msg3[1]) // 101 获取字符串索引为1的原始字节fmt.Println(msg3[2:7]) // llo Lfmt.Println(msg3[3:]) // lo Lee, My name is WangDeFa!!!fmt.Println(msg3[:4]) // Hell// 字符串分割msg4 := "Hello Lee, My name is WangDeFa!!!"fmt.Println(strings.Split(msg4, "e")) // [H llo L , My nam is WangD Fa!!!]// 是否包含某个字符串msg5 := "Hello Lee!!!"fmt.Println(strings.Contains(msg5, "ee")) // truefmt.Println(strings.Contains(msg5, "ele")) // false// 转换为大小写msg6 := "Hello Lee!!!"fmt.Println(strings.ToUpper(msg6)) // HELLO LEE!!!fmt.Println(strings.ToLower(msg6)) // hello lee!!!// 判断开头或结尾是否有指定字符串msg7 := "Hello Lee!!!"fmt.Println(strings.HasPrefix(msg7, "Hello")) // truefmt.Println(strings.HasSuffix(msg7, "Lee")) // falsefmt.Println(strings.HasSuffix(msg7, "Lee!!!")) // true// 查询字符串索引值msg8 := "Hello Lee!!!"fmt.Println(strings.Index(msg8, "ee")) // 7fmt.Println(strings.Index(msg8, "e")) // 1
}
++
--
运算符
++
--
是单独的运算符,不能添加到表达式中
package mainimport "fmt"func main() {a := 123a++fmt.Println(a) // 124a--fmt.Println(a) // 123
}
错误形式
a := 123
++a // Error: '++' unexpected
--a // Error: '--' unexpected
123 + a++ // Error: Cannot assign to 123 +
逻辑运算符
||
&&
!
只能应用于bool
值之间
循环 for ... := range ...
package mainimport "fmt"func main() {list := [...]any{"Lee", 25, "☹️"}for i, d := range list {fmt.Println(i, d) // 0 Lee 1 25 2 ☹️}
}
switch
和其他语言不同,不需要添加
break
package mainimport "fmt"func main() {var num intfmt.Scan(&num)switch num {case 1:fmt.Println(num)case 2:fmt.Println(num)case 3:fmt.Println(num)case 4, 5, 6:fmt.Println(num)default:fmt.Println("空")}
}
case
表达式
package mainimport "fmt"func main() {var score intfmt.Scan(&score)switch {case score >= 90 && score <= 120:fmt.Println("优秀")case score > 120:fmt.Println("作弊")default:fmt.Println("一般")}
}
实现类似其他语言不添加break
的效果(fallthrough
)
package mainimport "fmt"func main() {var num intfmt.Scan(&num) // 1 --> 一 二 三 2 --> 二 三switch num {case 1:fmt.Println("一")fallthroughcase 2:fmt.Println("二")fallthroughcase 3:fmt.Println("三")case 4, 5, 6:fmt.Println("四五六")default:fmt.Println("空")}
}
死循环
package mainimport "fmt"func main() {count := 0for {count++fmt.Println(count) // ...}
}
跳出循环
package mainimport "fmt"func main() {count := 0for {count++fmt.Println(count) // 1 - 100if count > 99 {break}}
}
package mainimport "fmt"func main() {count := 0for {count++fmt.Println(count) // 1 - 11if count > 10 {goto endPrint}}endPrint: // 标签fmt.Println("结束")
}
数组的CURD
package mainimport "fmt"func main() {list := []any{1, true, "Lee"}// 增res1 := append(list, "啥?")fmt.Println(list) // [1 true Lee]fmt.Println(res1) // [1 true Lee 啥?]res2 := append(list, res1...)fmt.Println(list) // [1 true Lee]fmt.Println(res2) // [1 true Lee 1 true Lee 啥?]// 改list[1] = "假"fmt.Println(list) // [1 假 Lee]// 查fmt.Println(list[2]) // Leefmt.Println(list[1:]) // [假 Lee]// 浅拷贝res3 := listres3[0] = 123fmt.Println(list) // [123 假 Lee]fmt.Println(res3) // [123 假 Lee]// 深克隆res4 := make([]any, len(list))copy(res4, list)res4[1] = 456fmt.Println(list) // [123 假 Lee]fmt.Println(res4) // [123 456 Lee]// 删 - 删除索引1list = append(list[:1], list[2])fmt.Println(list) // [123 Lee]
}
map
的CURD
CURD
package mainimport "fmt"func main() {//data := make(map[string]any)//data["name"] = "Lee"data := map[string]any{"name": "Lee",}// 改data["name"] = "Tom"// 增data["age"] = 18data["height"] = 171// 删delete(data, "height")// 查fmt.Printf("%v ---> %v ---> %v", data["name"], data["age"], data["height"]) // Tom ---> 18 ---> <nil>
}
拷贝
package mainimport "fmt"func main() {data1 := map[string]any{"name": "Lee","age": 18,"height": 171,}// 浅拷贝data2 := data1data2["name"] = "Tom"fmt.Printf("%v ---> %v ---> %v\\n", data1["name"], data1["age"], data1["height"]) // Tom ---> 18 ---> 171fmt.Printf("%v ---> %v ---> %v\\n", data2["name"], data2["age"], data2["height"]) // Tom ---> 18 ---> 171// 深克隆data3 := make(map[string]any)for key, value := range data1 {data3[key] = value}data3["name"] = "Lucy"fmt.Printf("%v ---> %v ---> %v\\n", data1["name"], data1["age"], data1["height"]) // Tom ---> 18 ---> 171fmt.Printf("%v ---> %v ---> %v\\n", data3["name"], data3["age"], data3["height"]) // Lucy ---> 18 ---> 171}
判断字段是否存在
package mainimport "fmt"func main() {data := map[string]any{"name": "Lee","age": 18,"height": 171,}height, hasHeight := data["height"]fmt.Println(height, hasHeight) // 171 truelike, hasLike := data["like"]fmt.Println(like, hasLike) // <nil> false
}
函数
基本函数
package mainimport "fmt"func sum1(a int, b int) (res int) {res = a + breturn res
}func sum2(a int, b int) int {res := a + breturn res
}func sum3(a int, b int) (int, int, int) {res := a + breturn a, b, res
}func sum4(a int, b int, c ...int) int {res := a + bfor _, v := range c {res += v}return res
}func main() {fmt.Println(sum1(1, 1)) // 2fmt.Println(sum2(1, 1)) // 2fmt.Println(sum3(1, 1)) // 1 1 2a, b, c := sum3(1, 1)fmt.Println(a, b, c) // 1 1 2fmt.Println(sum4(1, 2, 3, 4, 5)) // 15
}
函数类型
package mainimport "fmt"type demo func(int, int) intfunc sum(a int, b int) int {return a + b
}func max(a int, b int) int {if a > b {return a} else {return b}
}func main() {var d demod = sums := d(1, 2)fmt.Println(s) // 3d = maxm := d(1, 2)fmt.Println(m) // 2
}
回调函数
package mainimport "fmt"func sayHello(name string, callback func(string)) {fmt.Printf("%v: Hello!\\n", name)name = "Tom"if callback != nil {callback(name)}
}func sayHi(name string) {fmt.Printf("%v: Hi!\\n", name)
}func main() {sayHello("Lee", sayHi) // Lee: Hello! Tom: Hi!
}
匿名函数
package mainimport "fmt"func sayHello(name string, callback func(string)) {fmt.Printf("%v: Hello!\\n", name)name = "Tom"if callback != nil {callback(name)}
}func main() {sayHello("Lee", func(name string) {fmt.Printf("%v: Hi!\\n", name)}) // Lee: Hello! Tom: Hi!
}
立即执行函数
package mainimport "fmt"func main() {name := func(name string) string {return name}("Lee")fmt.Println(name) // Lee
}
闭包
package mainimport "fmt"func say() func(string) string {msg := "Hi, "return func(s string) string {msg += sreturn msg}
}func main() {str := say()fmt.Println(str("Lee")) // Hi, Leefmt.Println(str("-Tom.")) // Hi, Lee-Tom.
}
递归
package mainimport "fmt"func fun(n int) int {if n == 0 {return 1}return n * fun(n-1)
}func main() {fmt.Println(fun(3)) // 6
}
defer
先定义的后输出
package mainimport "fmt"func main() {fmt.Println(1)fmt.Println(2)fmt.Println(3)defer fmt.Println(4)defer fmt.Println(5)defer fmt.Println(6)defer fmt.Println(7)fmt.Println(8)fmt.Println(9)fmt.Println(0)// 结果:123 890 7654
}
init
初始化函数
执行顺序
变量函数 ---> init函数(按从上到下) ---> main函数
package mainimport "fmt"func init() {fmt.Println("init1")
}var data = func() any {fmt.Println("num")return nil
}()func init() {fmt.Println("init2")
}func main() {fmt.Println("main")
}func init() {fmt.Println("init3")
}// 结果: num init1 init2 init3 main
指针
package mainimport "fmt"func main() {var a = 123var b *int // int类型的指针变量// 打印变量值fmt.Println(b) // <nil>// 打印变量地址fmt.Println(&a) // 0xc0000ac008fmt.Println(&b) // 0xc0000a6018b = &a// 打印变量地址fmt.Println(b) // 0xc0000ac008// 打印变量值fmt.Println(*b) // 123
}
指向数组的指针
package mainimport "fmt"func main() {var a = []int{1, 2, 3}var b [3]*int// 打印变量值fmt.Println(b) // [<nil> <nil> <nil>]// 打印变量地址fmt.Println(&a) // &[1 2 3]fmt.Println(&a[0], &a[1], &a[2]) // 0xc00001e0d8 0xc00001e0e0 0xc00001e0e8fmt.Println(&b) // &[<nil> <nil> <nil>]fmt.Println(&b[0], &b[1], &b[2]) // 0xc000010048 0xc000010050 0xc000010058for i := range a {b[i] = &a[i]fmt.Println(b[i]) // 0xc00001e0d8 0xc00001e0e0 0xc00001e0e8fmt.Println(*b[i]) // 1 2 3}
}
类型定义
与 类型别名
package mainimport "fmt"// NewInt 自定义类型
type NewInt int// NewBool 类型别名
type NewBool = boolfunc main() {var a NewIntfmt.Println(a) // 0var b NewBoolfmt.Println(b) // false
}
结构体
package mainimport "fmt"type UserInfo struct {name stringage intheight float64
}func main() {var info UserInfoinfo.name = "Lee"info.age = 18info.height = 171fmt.Println(info) // {Lee 18 171}
}
匿名结构体
package mainimport "fmt"func main() {var info struct {name stringage intheight float64}info.name = "Lee"info.age = 18info.height = 171fmt.Println(info) // {Lee 18 171}
}
结构体赋值
package mainimport "fmt"type UserInfo struct {name stringage, height int
}func main() {var info UserInfo// 方式1info.name = "Lee"info.age = 18info.height = 171// 方式2info = UserInfo{"Lee", 18, 171,}// 方式3info = UserInfo{name: "Lee",height: 171,}fmt.Println(info) // {Lee 18 171}
}
结构体的指针
package mainimport "fmt"type UserInfo struct {name stringage, height int
}func main() {var lee *UserInfofmt.Println(lee) // <nil>fmt.Println(&lee) // 0xc000012028var tom = UserInfo{name: "Lee",age: 18,height: 171,}lee = &tomfmt.Println(lee) // &{Lee 18 171}fmt.Println(&lee) // 0xc000012028fmt.Println(*lee) // {Lee 18 171}
}
package mainimport "fmt"type UserInfo struct {name stringage, height int
}func main() {// 初始化结构体的指针var lee = new(UserInfo)fmt.Println(lee) // &{ 0 0}fmt.Println(&lee) // 0xc000012028var tom = UserInfo{name: "Lee",age: 18,height: 171,}lee = &tomfmt.Println(lee) // &{Lee 18 171}fmt.Println(&lee) // 0xc000012028fmt.Println(*lee) // {Lee 18 171}
}
结构体的嵌套
package mainimport "fmt"type UserInfo struct {name stringage, height int
}type Person struct {userInfo UserInfomsg string
}func main() {var tom = Person{userInfo: UserInfo{name: "Lee",age: 18,height: 171,},msg: "Hi",}fmt.Println(tom) // {{Lee 18 171} Hi}
}
结构体作为参数
package mainimport "fmt"type UserInfo struct {name stringage, height int
}type Person struct {userInfo UserInfomsg string
}func say1(person Person) {person.msg = "Hello"person.userInfo.name = "Tom"fmt.Println(person.msg, person.userInfo.name)
}func say2(person *Person) {person.msg = "Hello"person.userInfo.name = "Tom"fmt.Println(person.msg, person.userInfo.name)
}func main() {var person1 = Person{userInfo: UserInfo{name: "Lee",age: 18,height: 171,},msg: "Hi",}say1(person1) // Hello Tomfmt.Println(person1.msg) // Hifmt.Println(person1.userInfo.name) // Leevar person2 = Person{userInfo: UserInfo{name: "Lee",age: 18,height: 171,},msg: "Hi",}say2(&person2) // Hello Tomfmt.Println(person2.msg) // Hellofmt.Println(person2.userInfo.name) // Tom
}
方法
方法的接收者是结构体,包含值类型和引用类型时,那么值类型被复制,引用类型不被复制而是引用
package mainimport "fmt"type UserInfo struct {name stringage, height intlikes []string
}// info为接收者用于接收
func (info UserInfo) say() {info.age = 20info.likes[2] = "play"fmt.Println(info)
}func main() {var userInfo = UserInfo{name: "Lee",age: 18,height: 171,likes: []string{"吃", "喝", "玩", "乐"},}userInfo.say() // {Lee 20 171 [吃 喝 play 乐]} 注意值类型和引用类型的区别fmt.Println(userInfo) // {Lee 18 171 [吃 喝 play 乐]} 注意值类型和引用类型的区别
}
方法的接收者是指针类型结构体时,那么不被复制而是引用
package mainimport "fmt"type UserInfo struct {name stringage, height intlikes []string
}// info为接收者用于接收
func (info *UserInfo) say() {info.age = 20info.likes[2] = "play"fmt.Println(*info)
}func main() {var userInfo = UserInfo{name: "Lee",age: 18,height: 171,likes: []string{"吃", "喝", "玩", "乐"},}userInfo.say() // {Lee 20 171 [吃 喝 play 乐]} 注意值类型和引用类型的区别fmt.Println(userInfo) // {Lee 20 171 [吃 喝 play 乐]} 注意值类型和引用类型的区别
}
接口
接口内的方法必须定义,否则报错
package mainimport "fmt"// Sayer 说接口
type Sayer interface {say(msg string)
}// Mover 移动接口
type Mover interface {move(start int, end int) (name string, distance int)
}// Animaler 动物接口
type Animaler interface {SayerMover
}// Lee 结构体,存放姓名
type Lee struct {name string
}func (lee Lee) say(msg string) {fmt.Println(msg + lee.name)
}func (lee Lee) move(start int, end int) (name string, distance int) {distance = end - startreturn lee.name, distance
}func main() {var lee Animalerlee = Lee{name: "Lee"}lee.say("Hi,")name, distance := lee.move(0, 10)fmt.Println(name, distance)
}
OCP
: “开-闭”原则
package mainimport "fmt"type Animaler interface {eat()sleep()
}type Person struct {name string
}func (person Person) eat() {fmt.Println(person.name + ",吃...")
}func (person Person) sleep() {fmt.Println(person.name + ",睡...")
}func funA(animal Animaler) {animal.eat()animal.sleep()
}func (person Person) funB(animal Animaler) {animal.eat()animal.sleep()
}func main() {var animal Animaler = Person{name: "Dog"}animal.eat() // Dog,吃...animal.sleep() // Dog,睡...funA(animal) // Dog,吃... Dog,睡...var lee Animaler = Person{name: "Lee"}var tom Animaler = Person{name: "Tom"}person := Person{}person.funB(lee) // Lee,吃... Lee,睡...person.funB(tom) // Tom,吃... Tom,睡...
}
继承
结构体嵌套来实现继承
继承自User
的UserInfo
结构体
package mainimport "fmt"// User 父结构体
type User struct {say func(msg string)sleep func()
}// UserInfo 子结构体
type UserInfo struct {name stringage intheight float64User
}func main() {lee := UserInfo{name: "Lee",age: 18,height: 171.123,User: User{say: func(msg string) {fmt.Println(msg)},sleep: func() {fmt.Println("sleep...")},},}fmt.Println(lee) // {Lee 18 171.123 {0x102f8f610 0x102f8f690}}lee.say("Hi," + lee.name) // Hi,Leelee.User.say("Hi," + lee.name) // Hi,Leelee.User.sleep() // sleep...lee.sleep() // sleep...
}
构造函数
package mainimport "fmt"type UserInfo struct {name stringage intheight float64
}// initUserInfo 构造函数
func initUserInfo(name string, age int, height float64) *UserInfo {return &UserInfo{name: name, age: age, height: height}
}func main() {info := UserInfo{name: "Lee",age: 18,height: 171.123,}person := initUserInfo(info.name, info.age, info.height)fmt.Println(info) // {Lee 18 171.123}fmt.Println(person) // &{Lee 18 171.123}person.name = "Tom"fmt.Println(info) // {Lee 18 171.123}fmt.Println(person) // &{Tom 18 171.123}
}