Golang 整理1-基本语法

go / Golang 编程语言学习

官方提供了教程,中文版的教程地址 可以边练习边学习

语法声明格式

https://blog.go-zh.org/gos-declaration-syntax

从左到右的规则

  从左到右的写法与读法,符合读写习惯,尤其对于调用无名称的方法时尤为明显,如: func(a, b int) int { return a+b } (3, 4) 可以从左到右这样读出语义:一个函数,参数是 ab ( int)类型的,返回值是: int 类型的,函数体是 {return a+b } ,执行该函数传入的参数是 34

数组类型

  定义数组是 var a []int (英文读法是 array of int,所以写 []int 仍然是从左到右的方式 )  但是使用值的时候是: x = a[1]

指针

  指针的标识使用 * ,并且由于 * 有乘法的作用,所以定义指针可以: var p *int 但是使用是 *p 而不是  p*

函数参数类型的省略写法  

  多个相同类型的参数,只有最后一个不可以省略,其他可省略不写

func add(x int, y int) int {
	return x + y
}

// 参数 x 和 y 都是 int 类型,所以可以简略写为(省略掉参数 x 的类型标识):

func add(x, y int) int {
	return x + y
}
v

函数多返回值

  go 中函数可以返回多个值,而且可以命名返回值,命名的返回值会被视作定义在函数顶部的变量,进行命名的好处是可以当做文档说明,且当函数体比较短时,直接使用 return 后面不带任何具体变量, go 会自动返回命名返回值的变量。长的函数中它们会影响代码的可读性。

package main

import "fmt"

// 返回y,x两个变量
func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}

package main

import "fmt"

// 通过在返回值中定义了x,y变量,所以x,y 在函数体中不用定义,且返回时直接使用return。另外就是对于函数接收方的变量不一定要用命名返回值一样的名称。比如可以var a,b = split(17) 另外假如只需要使用第一个返回值,可以这样定义:var a,_ = split(17),同理,只使用第二个返回值:var _,b = split(17) 可以看到 _ 的作用就是忽略对应位置的返回值。
func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func main() {
	fmt.Println(split(17))
}

变量声明

  var 语句可以出现在包或函数级别

  使用关键字 var 声明: [var关键字] [变量名称] [变量类型]var a bool 要是多个相同类型的变量: var a,b,c bool ,假如多个不同类型的

package main

import "fmt"

func main() {
	var (
		a bool
		b int
	)
    // 没有赋值-则打印类型默认值 false 和 0
	fmt.Println(a, b)
}

变量赋值

没有明确初始值的变量声明会被赋予它们的 零值。数值类型为 0,布尔类型为 false,字符串为 ""(空字符串)。
  • 在变量声明时赋值: var i, j int = 1, 2  因为赋的值是明确的类型,所以可以可以省略为 var i,j = 1,2 变量会从初始值中获得类型
  • 函数内使用 := 赋值(只能在函数内且右边的值有明确类型的情况下可以使用) i,j := 1,2 等价于 var i,j = 1,2
package main

import "fmt"

func method1() {
	// 定义 a,b 变量并初始化
	var (
		a = 1
		b = "method1"
	)

	fmt.Println(a, b)
}

func method2() {
	// 定义 a,b 变量并初始化
	a, b := 2, "method2"
	fmt.Println(a, b)
}

func method3() {
	// 定义 a,b 变量并初始化
	var a, b = 3, "method3"
	fmt.Println(a, b)
}

func main() {
	method1()
	method2()
	method3()
}

基本类型

  • bool  布尔类型: true/false
  • string 字符串类型
  • int  int8  int16  int32  int64
  • uint uint8 uint16 uint32 uint64 uintptr uintptr 是 Go 内置类型,表示无符号整数,可存储一个完整的地址。常用于指针运算,
  • byte // uint8 的别名
  • rune // int32 的别名 // 表示一个 Unicode 码点
  • float32 float64
  • complex64 complex128

⭐️  需要注意的是 int, uintuintptr 在 32 位系统上通常为 32 位宽,在 64 位系统上则为 64 位宽

⭐️  Golangstring底层是通过 byte数组实现的。中文字符在 unicode下占 2个字节,在 utf-8编码下占 3个字节,而 Golang 默认编码正好是 utf-8 ,所以 Golang 处理中文长度时都需要转换为 []rune ,还要注意编码问题。

package main

import (
	"fmt"
)

func main() {
	str := "你好"

	// 6
	fmt.Println(len(str))

	// 强制转换为 []rune
	str_rune := ([]rune)(str)

	// [20320 22909]
	fmt.Println(str_rune)

	// 2
	fmt.Println(len(str_rune))
}

定义常量

  使用关键字 const 定义常量,常量即:一经定义就不可更改的变量,例如: const World = "世界" ,后面就不能修改 World 的值了。

  Golang 语言使用 管理代码模块,并且一定会有一个入口 main 包及 main 包下面的 main函数 做为启动函数,引入包使用关键字 import

package main

// 引入 fmt 包
import "fmt"

func main() {
	fmt.Println("你好")
}

假如引入多个包可以简单写:

package main

// 引入多个包简单写
import (
	"fmt"
	"math"
)

func main() {
	c := math.Sqrt(9)
	fmt.Printf("%.1f", c)
}

当引入的包中有冲突的时候可以给引入的包起一个别名,比如上面的例子中,给引入的 math 包起一个别名 m ,则可以这样:

package main

import (
	"fmt"
    // math 包起一个别名 m
	m "math"
)

func main() {
	// 使用别名 m 使用 math 包中的方法
	c := m.Sqrt(9)
	fmt.Printf("%.1f", c)
}

包可以简单理解为一个目录,相对于 main 包下创建一个目录 test ,那么在 test 下新建的 go 文件都是处于 test 包下,在同一个包下方法和变量是可以直接调用的,要是在不同的包之间进行方法及变量等访问,需要把方法或者变量的首字母大写:

package test

// test 包内可以访问 add 方法,但是不会被外部的包访问到
func add(a, b int) int {
	return a + b
}

// Sub 可以被其他包引入后访问到
func Sub(a, b int) int {
	return a - b
}