Skip to content

Golang 语法入门

Hello World

go
package main

import "fmt"

func main() {
	fmt.Println("hello world")
}

变量

go
package main

import "fmt"

// 全局变量
var ans = 123
var cnt int

func main() {
	// 单个局部变量
	a := 114514

	// 多个局部变量
	b, c := 114, 514

	fmt.Println(a, b, c)
	fmt.Println(ans)
	fmt.Println(cnt)
}

常量

使用 const 关键字

go
package main

import "fmt"

func main() {
	const PI = 3.14
	fmt.Println(PI)
}

函数

多返回值

go
package main

import "fmt"

// 前面是入参,后面是返回值
func getUpDown(n float64) (x float64, y float64) {
	return n - 1, n + 1
}

func main() {
	const PI = 3.14
	fmt.Println(getUpDown(PI))
}

init 和 import 函数

引用传参

Go 默认为值传递,传指针可以实现引用传递。

  • 函数中引用传递 *
  • 变量指向地址 &
go
func swap(x *int, y *int) {
    var temp int
    temp = *x    /* 保存 x 地址上的值 */
    *x = *y      /* 将 y 值赋给 x */
    *y = temp    /* 将 temp 值赋给 y */
}

func main() {
    // ...
    swap(&a, &b)
}

defer

defer 初识

return 后的调用,类似于 Java 的 finally。在 return 之后执行。

如果一个函数中有多个defer语句,它们会以栈顺序执行。

go
func Demo(){
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    defer fmt.Println("4")
}

func main() {
    Demo()
}
bash
4
3
2
1

recover 错误拦截

运行时panic异常一旦被引发就会导致程序崩溃。

recover 函数可以在当前的程序从运行时 panic 的状态中恢复并重新获得流程控制权。

recover只有在defer调用的函数中有效。

go
package main

import "fmt"

func Demo(i int) {
	// 必须放在最上面
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()

	var arr [10]int
	fmt.Println(arr[i])
}

func main() {
	Demo(10)
	fmt.Println("正常运行")
}
bash
err: runtime error: index out of range [10] with length 10
正常运行

slice 切片

slice 定义

Slice 的切片相当于动态数组

go
// 先定义再初始化
var arr []int
arr = make([]int, 3)

// 定义同时初始化
arr2 := make([]int, 3)

// 获取长度
len(arr)
// 获取容量
cap(arr)

append & copy

copy:拷贝切片

append:追加元素

对于追加不需要考虑容量限制,切片会自动扩容(原容量2倍)。

go
package main

import "fmt"

func main() {
	var arr []int
    // 需要赋值给自己(语法难崩...)
	arr = append(arr, 1, 2, 3)
	fmt.Println(arr)
}

Map 集合

吐槽:Map 叫集合、Slice 叫切片...终于知道为什么要说英文名了 😅🙏🏻

go
package main

import "fmt"

func main() {
	// key: string
	// value: int
	m := make(map[string]int, 10)
	m["apple"] = 1
	m["banana"] = 2

	// 字面量创建
	n := map[string]int{
		"apple":  1,
		"banana": 2,
	}

	// 遍历 Map
	for k, v := range m {
		fmt.Printf("key=%s, value=%d\n", k, v)
	}

	// 删除元组
	delete(n, "apple")
}

struct 结构体

结构体在函数入参中是值传递

go
package main

import "fmt"

type Book struct {
	title string
	price float64
}

func increasePrice(book *Book) {
	book.price *= 1.2
}

func main() {
	var book Book
	book.title = "《Golang 从入门到字节》"
	book.price = 100

	fmt.Println(book)

	// 结构体是值传递!!!
	increasePrice(&book)

	fmt.Println(book)

}
bash
{《Golang 从入门到字节》 100}
{《Golang 从入门到字节》 120}

面向对象

封装

Golang 不是面向对象编程的语言,使用结构体作为对象。

首字母大写表示 public,首字母小写表示 private。

go
package main

import "fmt"

type Student struct {
	name  string
	age   int
	score int
}

func (s *Student) GetName() string {
	return s.name
}

func (s *Student) SetName(name string) {
	s.name = name
}

func (s *Student) Show() {
	fmt.Println(*s)
}

func main() {
	student := Student{
		name:  "wmh",
		age:   22,
		score: 100,
	}
	fmt.Println(student.GetName())
	student.SetName("yixuan")
	student.Show()
}

继承

😅 这语法要吐了

go
package main

import "fmt"

type Student struct {
	name  string
	age   int
	score int
}

func (s *Student) GetName() string {
	return s.name
}

func (s *Student) SetName(name string) {
	s.name = name
}

func (s *Student) Show() {
	fmt.Println(*s)
}

// 继承 Student
type CollageStudent struct {
	Student
	class string
}

// 重写子类方法
func (s *CollageStudent) Show() {
	fmt.Println(*s)
}

func main() {
	var stu CollageStudent
	stu.age = 22
	stu.class = "软件工程"
	stu.name = "wmh"
	fmt.Println(stu.GetName())
	stu.SetName("yixuan")
	stu.Show()
}

多态

多态三要素

使用 interface 接口实现多态

  • 定义接口
  • 子类实现了父类的全部接口方法
  • 接口指针指向子类的具体数据变量
go
package main

import "fmt"

// 接口
type Person interface {
	talk()
}

type Student struct {
	name string
}

func (stu *Student) talk() {
	fmt.Println(stu.name + ": student talk")
}

type Teacher struct {
	name string
}

func (tea *Teacher) talk() {
	fmt.Println(tea.name + ": teacher talk")
}

func main() {
	var p1, p2 Person
	p1 = &Student{"wmh"}
	p1.talk()
	p2 = &Teacher{"yx"}
	p2.talk()
}
bash
wmh: student talk
yx: teacher talk

空接口

可以使用 interface{}引用任意类型数据(类似于 Java 的 Object,或者 TS 的 any)

go
package main

import "fmt"

func myPrint(arg interface{}) {
	fmt.Println("------")
	fmt.Println(arg)
	fmt.Println("------")
}

func main() {
	n := 114514
	str := "wahaha"
	myPrint(n)
	myPrint(str)
}

反射

类型断言

将空接口类型(类比 Object)判断并转换成具体子类

go
func main() {
	var x interface{} = 114514
	n, ok := x.(int)
	fmt.Println(n, ok)
	// 114514 true

	var y interface{} = "114514"
	m, ok := y.(int)
	fmt.Println(m, ok)
	// 0 false
}

Released under the MIT License.