Go语言基础

程序结构

变量

  • 标准语法:var 变量名字 类型 = 表达式 var i int = 1
  • 简短语法:变量名字 := 表达式 j := 2

常量

  • 关键字:const
  • 语法:const 常量名 = 编译期确定的值
  • 常量值:字符、字符串、布尔值、数值。
  • 常量不能用 := 语法声明

类型

  • 语法:type 类型名字 底层类型
type Person struct {
    name string
    age int
}

控制语句

for

Go中唯一的循环结构

sum := 0
for i := 0; i < 10; i++ {
  sum += i
}

if-else

func sqrt(x float64) string {
    if x < 0 {
            return sqrt(-x) + "i"
    }
      return fmt.Sprint(math.Sqrt(x))
}
  • 特点:可以在条件表达式前执行一个简单的语句
func pow(x, n, lim float64) float64 {
      if v := math.Pow(x, n); v < lim {
          return v
      }
      return lim
}

switch-case

  • 只执行匹配的case(Go自动加了break语句)
  • case 无需为常量,且取值不必为整数
    switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        // freebsd, openbsd,
        // plan9, windows...
        fmt.Printf("%s.\n", os)
    }

defer

  • defer 语句会将函数推迟到外层函数返回之后执行。
  • 推迟的函数调用会被压入一个栈中,按照后进先出的顺序调用。
defer fmt.Println("world")
fmt.Println("hello")

包和文件

  • 文件:组织Go代码
  • 包:管理Go文件,支持模块化,独立命名空间
  • 导出规则:如果一个名字是大写字母开头的,那么该名字是导出的,包外可访问
  • 匿名导入:它会计算包级变量的初始化表达式和执行导入包的init初始化函数

基础数据类型

整型

  • 有符号整数:int8、int16、int32、int64、int、rune
  • 无符号整数:uint8、uint16、uint32、uint64、uint、uintptr、byte
  • int、uint、uintptr:在32位系统上是32位,在64位系统上是64位
  • byte:等同于uint8,表示一个字节
  • rune:等同于int32,表示一个Unicode码点

浮点型

  • 浮点数:float32、float64
  • 复数:complex64、complex128

布尔型

bool:true、false

字符串

  • string:默认使用UTF8编码
  • 常用包:bytes、strings、strconv、unicode

零值

声明但未初始化的变量会被赋予零值

  • 数值类型:0
  • 布尔类型:false
  • 字符串:""
var i int
var b bool
var s string
fmt.Printf("%v %v %q\n", i, b, s) // 0 false ""

类型转换

表达式 T(v) 将值 v 转换为类型 T

i := 42
f := float64(i)
u := uint(f)

复合数据类型

数组

  • 声明:var a [3]int
  • 初始化:var q [3]int = [3]int{1, 2, 3}
  • 简短写法:a := [3]int{1, 2, 3}

切片

  • 声明:var s []int
  • 添加元素:s = append(s, 1, 2, 3)
  • 切片操作:s[i:j],表示s的从第i个元素开始到第j-1个元素的子序列。
  • 切片的长度:它所包含的元素个数,len(s)
  • 切片的容量:从它的第一个元素开始数,到其底层数组元素末尾的个数,cap(s)
  • 切片的零值:nil

哈希表

  • 创建
// m1 = nil
m1 := make(map[string]int)

// m2 = {}
m2 := map[string]int{}

// m3 = {"age":18}
m2 := map[string]int{
  "age": 18,
}
  • 读写
m[key] = elem // 新增或更新
elem = m[key] // 获取
delete(m, key) // 删除
elem, ok := m[key] // 判断键是否存在

结构体

  • 定义
type Employee struct {
    ID        int
    Name      string
}
  • 初始化
e := Employee{
  ID: 123,
  Name: "test",
}
  • JSON序列化
type Employee struct {
    ID        int `json:"id"`
    Name      string `json:"name"`
}

data, err := json.Marshal(e)
if err != nil {
    log.Fatalf("JSON marshaling failed: %v", err)
}
fmt.Printf("%s\n", data)

range

// 遍历数组
for index, value := range array {
    fmt.Printf("%d %d\n", index, value)
}

// 忽略index
for _, value := range array {
    fmt.Printf("%d\n", value)
}

// 忽略value
for index := range array {
    fmt.Printf("%d\n", index)
}

// 遍历哈希表
for key, value := range map {
    fmt.Printf("%d %d\n", key, value)
}

函数

声明

func name(parameter-list) (result-list) {
    body
}

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

// 如果连续参数类型相同,可以简写为:
func add(x, y int) int {
      return x + y
}

多返回值

在Go中,函数可以返回任意数量的返回值。

func swap(x, y string) (string, string) {
    return y, x
}

方法

声明

方法就是一类带特殊的接收者参数的函数。

// 方式1:值类型
func (t T) name(parameter-list) (result-list) {
    body
}

// 方式2:指针类型
func (t *T) name(parameter-list) (result-list) {
    body
}

方式1和方式2的区别:调用方法时,前者是深拷贝,后者是浅拷贝。

封装

type Counter struct { n int }
func (c *Counter) N() int     { return c.n }
func (c *Counter) Increment() { c.n++ }
func (c *Counter) Reset()     { c.n = 0 }

接口

声明

type error interface {
    Error() string
}

实现

隐式实现:一个类型拥有某接口的所有方法,则该类型就实现了这个接口。

// errorString类型
type errorString struct { 
    text string
}

// 实现error接口
func (e *errorString) Error() string {
    return e.text 
}

使用

func New(text string) error { 
    return &errorString{text}
}

空接口

  • 形式:interface{}
  • 空接口可保存任何类型的值。
  • 空接口被用来处理未知类型的值。
func describe(i interface{}) {
      fmt.Printf("(%v, %T)\n", i, i)
}

func main() {
      var i interface{}
      describe(i) // (, )

      i = 42
      describe(i) // (42, int)

      i = "hello"
      describe(i) // (hello, string)
}

类型断言

  • 类型断言:提供了访问接口值底层具体值的方式。
  • t := i.(T):断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t。若 i 并未保存 T 类型的值,则会触发panic异常。
  • t, ok := i.(T) 判断接口值 i 是否保存了具体类型 T,如果为true,那么 t 将会是其底层值,否则而 t 将为 T 类型的零值。不会触发panic异常。

类型选择

  • 类型选择:一种按顺序从几个类型断言中选择分支的结构。
switch v := i.(type) {
case T:
    // v 的类型为 T
case S:
    // v 的类型为 S
default:
    // 没有匹配,v 与 i 的类型相同
}

本文由mdnice多平台发布

你可能感兴趣的:(Go语言基础)