> 文章列表 > Go(一):Go基础语法入门

Go(一):Go基础语法入门

Go(一):Go基础语法入门

Go基础语法入门

    • 第一个go程序
    • 变量
    • 常量
    • 数据类型
    • 字符串处理
    • `++` `--` 运算符
    • 逻辑运算符
    • 循环 `for ... := range ...`
    • `switch`
    • 死循环
    • 数组的CURD
    • `map`的CURD
    • 函数
    • `defer`
    • `init`初始化函数
    • 指针
    • `类型定义` 与 `类型别名`
    • 结构体
    • 方法
    • 接口
    • 继承
    • 构造函数

第一个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开始,每次调用自动加1
    const (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,睡...
}

继承

结构体嵌套来实现继承

继承自UserUserInfo结构体

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}
}