go语言基础知识汇总

PowerMichael · · 1456 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、go语言简介

  • 天然支持高并发
  • 内存自动回收,不需要开发人员管理内存
  • 支持管道,从而支持多个协程之间通信
  • 多返回值,一个函数可以允许多个返回值
  • 异常和错误的区分,异常是不能预料到的事情发生了,错误是预料到的事情发生了。

    二、理解gopath

  • gopath go项目的工作目录,目录下面包含三个目录,src,pkg,bin
  • goroot go源码的安装路径
  • gobin 存放go编译后生成的可执行文件
  • go get 执行go get会把源码放在第一个gopath的src目录下面

    三、go基础知识

    3.1 基本数据结构和操作符


    1. 文件名&关键字&标识符(略)
        1. _是特殊标识符,用来忽略结果
    1. Go程序基本结构
        1. 任何一个代码文件隶属于一个包
        1. import 关键字,引用其他包:
        1. golang可执行程序,package main,并且有且只有一个main入口函数
        1. 包中函数调用:a.同一个包中直接实用名称调用;b。不同包中的函数通过包名+点+函数名称进行调用
        1. 包访问控制规则:大写意味函数公有;小写意味函数私有;
    1. 常量和变量
      • 常量使用const 修饰,代表永远是只读的,不能修改。
        1. const 只能修饰boolean,number(int相关类型、浮点类型、complex)和string。
    1. 数据类型和操作符
      • 值类型:变量直接存储值,内存通常在栈中分配。
      • 值类型:基本数据类型int、float、bool、string以及数组和struct。
      • 引用类型:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配。通过GC回收。
      • 引用类型:指针、slice、map、chan等都是引用类型
      • 在函数内部声明的变量叫做局部变量,生命周期仅限于函数内部。
      • 在函数外部声明的变量叫做全局变量,生命周期作用于整个包,如果是大写的,则作用于整个程序。
      • bool类型,只能存true和false
      • 相关操作符, !、&&、||
      • 数字类型,主要有int、int8、int16、int32、int64、uint8、uint16、uint32、uint64、float32、float64
      • 类型转换,type(variable),比如:var a int=8; var b int32=int32(a)
      • 逻辑操作符:== 、!=、<、<=、>和 >=
      • 数学操作符:+、-、*、/等等
    1. 字符串类型
      • 字符类型:var a byte
      • 字符串类型: var str string
      • 字符串表示两种方式: 1)双引号2)``(不需要转义)

        3.2 字符串处理&时间和日期类型&指针类型&流程控制&函数详解

    2. strings和strconv使用
      • strings.HasPrefix(s string, prefix string) bool:判断字符串s是否以prefix开头。
        1. strings.HasSuffix(s string, suffix string) bool:判断字符串s是否以suffix结尾。
        1. strings.Index(s string, str string) int:判断str在s中首次出现的位置,如果没有出现,则返回-1
        1. strings.LastIndex(s string, str string) int:判断str在s中最后出现的位置,如果没有出现,则返回-1
        1. strings.Replace(str string, old string, new string, n int):字符串替换
        1. strings.Count(str string, substr string)int:字符串计数
        1. strings.Repeat(str string, count int)string:重复count次str
        1. strings.ToLower(str string)string:转为小写
        1. strings.ToUpper(str string)string:转为大写
      • strings.TrimSpace(str string):去掉字符串首尾空白字符
      • strings.Trim(str string, cut string):去掉字符串首尾cut字符
      • strings.TrimLeft(str string, cut string):去掉字符串首cut字符
      • strings.TrimRight(str string, cut string):去掉字符串首cut字符
      • strings.Field(str string):返回str空格分隔的所有子串的slice
      • strings.Split(str string, split string):返回str split分隔的所有子串的slice
      • strings.Join(s1 []string, sep string):用sep把s1中的所有元素链接起来
      • strings.Itoa(i int):把一个整数i转成字符串
      • strings.Atoi(str string)(int, error):把一个字符串转成整数
    3. Go中的时间和日期类型
        1. time包
        1. time.Time类型,用来表示时间
        1. 获取当前时间, now := time.Now()
        1. time.Now().Day(),time.Now().Minute(),time.Now().Month(),time.Now().Year()
        1. 格式化,fmt.Printf("%02d/%02d%02d %02d:%02d:%02d", now.Year()…)
        1. time.Duration用来表示纳秒
    4. 指针类型
        1. 普通类型,变量存的就是值,也叫值类型
        1. 获取变量的地址,用&,比如: var a int, 获取a的地址:&a
        1. 指针类型,变量存的是一个地址,这个地址存的才是值
        1. 获取指针类型所指向的值,使用:,比如:var p int, 使用*p获取p指向的值
    5. 流程控制
        1. If / else分支判断
        1. switch case语句,可以使用fallthrough强制执行后面的case代码
        1. for 语句
        1. for range 语句
        1. break continue语句
        1. goto 和 label 语句 (明天补充)
    6. 函数详解
        1. 声明语法:func 函数名 (参数列表) [(返回值列表)] {}
        1. golang函数特点:
      • a. 不支持重载,一个包不能有两个名字一样的函数
      • b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
      • c. 匿名函数
      • d. 多返回值
        1. 函数参数传递方式:
      • 1). 值传递
      • 2). 引用传递
        注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
        注意2:map、slice、chan、指针、interface默认以引用的方式传递
        1. _标识符,用来忽略返回值:
        1. 可变参数:func add(a int, b int, arg…int) int {} //两个或多个参数
      • 注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数
        1. defer用途:
        1. 当函数返回时,执行defer语句。因此,可以用来做资源清理
        1. 多个defer语句,按先进后出的方式执行
        1. defer语句中的变量,在defer声明时就决定了。
        1. defer的用途:关闭文件句柄;释放资源;关闭数据库连接

3.3 内置函数、递归函数、闭包


内置函数

    1. close:主要用来关闭channel
    1. len:用来求长度,比如string、array、slice、map、channel
    1. new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
    1. make:用来分配内存,主要用来分配引用类型,比如chan、map、slice
    1. append:用来追加元素到数组、slice中
    1. panic和recover:用来做不可预料的异常捕获
    1. new和make的区别
      • New与make都是用来分配内存。不同点:new用来分配值类型,make用来分配引用类型;new返回的是一个指针,make返回的是值类型。
        递归函数

    1. 一个函数调用自己,就叫做递归。
    1. 斐波那契数
    1. 递归的设计原则
      • 1)一个大的问题能够分解成相似的小问题
      • 2)定义好出口条件
        闭包

  • 一个函数和与其相关的引用环境而组合成的实体。

    3.4 数组和切片、map数据结构

    数组

    1. 数组:是同一种数据类型的固定长度的序列。
    2. 数组定义:var a [len]int,比如:var a[5]int
    3. 长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型
    4. 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
    5. 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
    6. 数组是值类型,因此改变副本的值,不会改变本身的值
    7. 数组初始化
      切片

    8. 切片:切片是数组的一个引用,因此切片是引用类型
    9. 切片的长度可以改变,因此,切片是一个可变的数组
    10. 切片遍历方式和数组一样,可以用len()求长度
    11. cap可以求出slice最大的容量,0 <= len(slice) <= (array),其中array是slice引用的数组
    12. 切片的定义:var 变量名 []类型,比如 var str []string var arr []int
Slice的数据结构
Type slice struct {
    ptr *[5]type
    len int
    cap int
}
Cap:不指定的话,默认为2^0 2^1 2^2 2^n n为元素的个数
  1. 通过make来创建切片(另一种通过数组创建切片)
    • var slice []type = make([]type, len)
    • slice := make([]type, len)
    • slice := make([]type, len, cap)
  2. 用append内置函数操作切片,当切片容量不够,会自动扩容,创建一个新的地址。
  3. For range 遍历切片
  4. 切片拷贝
  5. string与slice
    • string底层就是一个byte的数组,因此,也可以进行切片操作
      Type string struct {
      ptr *[5]byte
      len int
      }
    • 想要改变string中的字符值,首先需要把字符串转换成byte切片
  6. 排序和查找操作
    • sort.Ints对整数进行排序, sort.Strings对字符串进行排序, sort.Float64s对浮点数排序
    • sort.SearchInts(a []int, b int) 从数组a中查找b,前提是a必须有序
    • sort.SearchFloats(a []float64, b float64) 从数组a中查找b,前提是a必须有序
    • sort.SearchStrings(a []string, b string) 从数组a中查找b,前提是a必须有序
      map数据结构

  7. key-value的数据结构,又叫字典或关联数组
    • 声明 var a map[string]string
    • 声明是不会分配内存的,初始化需要make
  8. map相关操作
    • var a = map[string]string{"key":"value"}
    • a = make(map[string]string, 10)
    • a[“hello”] = “world” //插入或者更新
    • Val, ok := a[“hello”] // 查找
    • for k, v := range a //遍历
    • delete(a, “hello”) //删除
  9. map是引用类型
  10. slice of map
    • 字典类型的数组
    • Map类型的slice初始化
      Items := make([]map[int][int], 5)
      For I := 0; I < 5; i++ {
      items[i] = make(map[int][int])
      }
  11. map排序
    • a. 先获取所有key,把key进行排序
    • b. 按照排序好的key,进行遍历
  12. Map反转
    • a. 初始化另外一个map,把key、value互换即可

      3.5 package介绍


  13. golang中的包
    • a. golang目前有150个标准的包,覆盖了几乎所有的基础库
    • b. golang.org有所有包的文档,没事都翻翻
  14. 线程同步
    • a. import(“sync”)
    • b. 互斥锁, var mu sync.Mutex
    • c. 读写锁, var mu sync.RWMutex
    • d. 为什么要有锁:十字路口是公有的资源,红绿灯就是锁。为了避免小车争抢资源就要上锁。
  15. 课后作业
    实现一个冒泡排序、选择排序、插入排序、快速排序(参考书籍及搜索引擎)

    3.6 结构体&方法&接口

    结构体的特点

    1. 用来自定义复杂数据结构
    2. struct里面可以包含多个字段(属性)
    3. struct类型可以定义方法,注意和函数的区分
    4. struct类型是值类型
    5. struct类型可以嵌套
    6. Go语言没有class类型,只有struct类型
      结构体的定义以及初始化
  16. struct 声明:
  17. struct 中字段访问:和其他语言一样,使用点
  18. struct定义的三种形式:
    1. var stu Student
    2. var stu *Student = new (Student)
    3. var stu *Student = &Student{}
      • 其中2和3返回的都是指向结构体的指针,访问形式:a. stu.Name、stu.Age和stu.Score或者 (stu).Name、(stu).Age等
  19. struct的内存布局:struct中的所有字段在内存是连续的,布局如下:
  20. 链表定义
    • 每个节点包含下一个节点的地址,这样把所有的节点串起来了,通常把
      链表中的第一个节点叫做链表头
      type Student struct {
      Name string
      Next* Student
      }
  21. 双链表定义
    • 如果有两个指针分别指向前一个节点和后一个节点,我们叫做双链表
      type Student struct {
      Name string
      Next* Student
      Prev* Student
      }
  22. 二叉树定义
    • 如果每个节点有两个指针分别用来指向左子树和右子树,我们把这样的结构叫做二叉树
type Student struct {
       Name string
       left* Student
       right* Student
}
  1. 结构体是用户单独定义的类型,不能和其他类型进行强制转换
  2. golang中的struct没有构造函数,一般可以使用工厂模式来解决这个问题
type student struct {
    Name string
    Age     int
}

func NewStudent(name string, age int) *student {
    return &student{
        Name:name,
        Age:age,
    }
}
func main()  {
    s := new(student)
    a := NewStudent("tony", 23)
    s = a
    fmt.Println(*s)
    fmt.Println(*a)

}
  1. 再次强调:
    • make 用来创建map、slice、channel、interface,new用来创建值类型
  2. 我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化
type student struct {
    Name stirng  "this is name field"
    Age int      "this is age field"
}
  1. 结构体中字段可以没有名字,即匿名字段
type Train struct {
        Car
        Start time.Time
        int
}

3.7 方法


  1. Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是struct
    • 定义:func (recevier type) methodName(参数列表)(返回值列表){}
  2. 方法的调用
type A struct {
    a int
}

func (this A) test() {
    fmt.Println(this.a)
}

var t A
t.test()
  1. 方法和函数的区别
    • 函数调用: function(variable, 参数列表)
    • 方法调用:variable.function(参数列表)
  2. 指针receiver vs 值receiver
    • 本质上和函数的值传递和地址传递是一样的
  3. 方法的访问控制,通过大小写控制
  4. 继承
    • 如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现了继承。
  5. 组合和匿名字段
    • 如果一个struct嵌套了另一个有名结构体,那么这个模式就叫组合
  6. 多重继承
    • 如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现了多重继承。
  7. 实现String()
    • 如果一个变量实现了String()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出。

      3.8 接口

      接口的定义

  8. interface类型可以定义一组方法,但是这些方法不需要实现。并且interface不能包含任何变量。
  9. 定义接口
    type example interface {
    Method1(parse1) return1
    method2(parse1) return1
    }
  10. interface类型默认是一个指针
  11. 接口实现
    • a. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字
    • b. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
    • c. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
  12. 多态
    一种事物的多种形态,都可以按照统一的接口进行操作
  13. 接口嵌套
    一个接口可以嵌套在另外的接口
package main

type ReadWrite interface {
    Read()
    Write()

}

type Lock interface {
    Lock()
    Unlock()
}

type File interface {
    ReadWrite
    Lock
    Close()
}

8.类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法进行转换:

var t int 
var x interface{}
x = t
y, ok := x.(int) //转成int
if ok {...}
switch b := x.(type) {
    case int:
        fmt.Println("int:", b)
    case string:
        fmt.Println("string", b)
    default:
        fmt.Println("i don't know")
    }
  1. 空接口 interface{},空接口没有任何方案,所有类型都实现了空接口,可以使用空接口
var a int
var b interface{}
b  = a
  1. 判断一个变量是否实现了指定接口

    • if sv, ok := v.(Stringer); ok {}
  2. 问题
      1. 指针类型和值类型的区别
      1. 实现一个通用的链表类
      1. 实现一个负载均衡调度算法,支持随机、轮训等算法
      1. 变量slice和接口slice之间赋值操作,for range???

        3.9 反射


  3. 反射:可以在运行时动态获取变量的相关信息Import (“reflect”)
    • a. reflect.TypeOf,获取变量的类型,返回reflect.Type类型
    • b. reflect.ValueOf,获取变量的值,返回reflect.Value类型
    • c. reflect.Value.Kind,获取变量的类别,返回一个常量
    • d. reflect.Value.Interface(),转换成interface{}类型
    • 变量 <--> interface <--> Reflect.Value
  4. 获取变量的值
    • reflect.ValueOf(x).Float()
    • reflect.ValueOf(x).Int()
    • reflect.ValueOf(x).String()
    • reflect.ValueOf(x).Bool()
  5. 通过反射的来改变变量的值
    • reflect.Value.SetXX相关方法,比如:
    • reflect.Value.SetFloat(),设置浮点数
    • reflect.Value.SetInt(),设置整数
    • reflect.Value.SetString(),设置字符串
package main

import (
    "fmt"
    "reflect"
)

func main() {

    var a float64
    fv := reflect.ValueOf(&a)
    fv.Elem().SetFloat(3.3)
    fmt.Printf("%v\n", a)
}
fv.Elem()用来获取指针指向的变量
  1. 用反射操作结构体 ???
    • a. reflect.Value.NumField()获取结构体中字段的个数
    • b. reflect.Value.Method(n).Call来调用结构体中的方法

      3.9 终端以及文件操作

  2. 终端读写
    • os.Stdin:标准输入
    • os.Stdout:标准输出
    • os.Stderr:标准错误输出
  3. 带缓冲区的读写:
    • var inputReader *bufio.Reader //声明一个结构体类型的变量
    • inputReader = bufio.NewReader(os.Stdin) //读取标准输入
    • input, err = inputReader.ReadString('\n') // 读取换行
  4. os.File封装所有文件相关操作,之前讲的 os.Stdin,os.Stdout, os.Stderr都是*os.File
    • 打开一个文件进行读操作: os.Open(name string) (*File, error)
    • 关闭一个文件:File.Close()
    • bufio.NewReader //构造一个reader结构体
    • inputReader.ReadString //逐行读取
    • ioutil.ReadFile(inputFile) //读取整个文件
    • ioutil.WriteFile(outputFile,buf,0x644) //写入整个文件
    • gzip.NewReader(fi) //构造一个压缩文件的reader结构体
  5. 文件写入
    • os.OpenFile(“output.dat”, os.O_WRONLY|os.O_CREATE, 0666)
    • 第二个参数:文件打开模式:
    • 第三个参数:权限控制:
    • bufio.NewWriter(outputFile) //构建一个写入文件的writer
    • outputWriter.WriteString(outputString) //写入文件
    • outputWriter.Flush() 提交
package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

func main()  {
    inputFile, err := os.Open("file")
    if err != nil {
        fmt.Printf("open file err:%v\n", err)
        return
    }

    defer inputFile.Close()

    inputReader := bufio.NewReader(inputFile)
    for {
        inputString, readerError := inputReader.ReadString('\n')
        if readerError == io.EOF {
            return
        }
        fmt.Printf("the input was %s", inputString)
    }

}
//读取以及写入整个文件
package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

func main()  {
    inputFile := "file"
    outputFile := "output_file"
    buf, err := ioutil.ReadFile(inputFile)
    if err != nil {
        fmt.Fprintf(os.Stderr, "File Error:%s\n", err)
        return
    }
    fmt.Printf("%s\n",string(buf))
    err = ioutil.WriteFile(outputFile,buf,0x644)
    if err != nil {
        panic(err.Error())
    }

}
//读取压缩文件
gzip.NewReader(fi)
//写入文件
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main()  {
    outputFile, outputErr := os.OpenFile("new_file", os.O_WRONLY|os.O_CREATE,0666)
    if outputErr != nil {
        fmt.Printf("An error occurred with file creation\n")
        return
    }
    defer outputFile.Close()
    outputWriter := bufio.NewWriter(outputFile)
    outputString := "hello world!\n"
    for i:= 0;i < 10; i++ {
        outputWriter.WriteString(outputString)
    }
    outputWriter.Flush()
}
  1. 拷贝文件 io.Copy(dst, src)
  2. os.Args是一个string的切片,用来存储所有的命令行参数
  3. flag包的使用,用来解析命令行参数:
    flag.BoolVar(&test, "b", false, "print on newline")
    flag.StringVar(&str, "s", "", "print on newline")
    flag.IntVar(&count, "c", 1001, "print on newline")
package main

import (
    "flag"
    "fmt"
)

func main()  {
    var test bool
    var str string
    var count int

    flag.BoolVar(&test, "b", false, "print on newline")
    flag.StringVar(&str, "s", "hello", "print on newline")
    flag.IntVar(&count, "c", 1001, "print on newline")
    flag.Parse()

    fmt.Println(test,str,count)
}
package main

import (
    "bufio"
    "fmt"
    "os"
)

//带缓冲的区的终端读写
func main()  {
    fmt.Fprintf(os.Stdout,"%s\n","hello world!-unbuffered")
    buf := bufio.NewWriter(os.Stdout)
    fmt.Fprintf(buf, "%s\n", "hello world!-buffered" )
    buf.Flush()
}

四、中阶知识

4.1 json数据协议

  1. golang --> json字符串 --> 网络传输 --> 程序 --> 其他语言
    1. 导入包:Import “encoding/json”
    2. 序列化: json.Marshal(data interface{}) //json化
    3. 反序列化: json.UnMarshal(data []byte, v interface{}) //解析json
  2. json序列化结构体
  3. json序列化map

    4.2 错误处理

  4. 定义错误 var errNotFound error = errors.New("Not found error")
  5. 自定义错误
  6. 如何判断自定义错误
  7. pannic 这一部分参考俯瞰四维

    五、并发编程

    六、高阶编程

    6.1 tcp编程

    6.2 redis

    redis是个开源的高性能的key-value的内存数据库,可以把它当成远程的数据结构。支持的value类型非常多,比如string、list(链表)、set(集合)、hash表等等。redis性能非常高,单机能够达到15w qps,通常适合做缓存。使用第三方开源的redis库: github.com/garyburd/redigo/redis

    • 链接redis c, err := redis.Dial("tcp", "localhost:6379")
    • Set 接口 _, err = c.Do("Set", "abc", 100) r, err := redis.Int(c.Do("Get", "abc"))
    • Hash表 _, err = c.Do("HSet", "books", "abc", 100) r, err := redis.Int(c.Do("HGet", "books", "abc"))
    • . 批量Set _, err = c.Do("MSet", "abc", 100, "efg", 300) r, err := redis.Ints(c.Do("MGet", "abc", "efg"))
    • 过期时间 _, err = c.Do("expire", "abc", 10)
    • 队列操作 _, err = c.Do("lpush", "book_list", "abc", "ceg", 300) r, err := redis.String(c.Do("lpop", "book_list"))

      6.3 http编程

      特点

    • a. Go原生支持http,import(“net/http”)
    • b. Go的http服务性能和nginx比较接近
    • c. 几行代码就可以实现一个web服务
  8. 处理http请求
    使用 net/http 包提供的 http.ListenAndServe() 方法,可以在指定的地址进行监听, 开启一个HTTP,服务端该方法的原型:func ListenAndServe(addr string, handler Handler) error <br>
    第二个参数表示服务端处理程序, 通常为空,这意味着服务端调用 http.DefaultServeMux 进行处理,而服务端编写的业务逻 辑处理程序 http.Handle() 或 http.HandleFunc() 默认注入 http.DefaultServeMux 中
  9. 处理https请求 func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error
  10. 路由 http.HandleFunc()方法接受两个参数
    • 第一个参数是HTTP请求的 目标路径"/hello",该参数值可以是字符串,也可以是字符串形式的正则表达式
    • 第二个参数指定具体的回调方法,比如helloHandler
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(“hello beifeng!”))
    })
  1. post访问
resp, err:=http.Get(“.....”)

defer resp.Body.Close()

body,err:=ioutil.ReadAll(resp.Body)

fmt.Println(string(body))
  1. post访问
resp, err:=http.Post(“.....”, ”application/x-www-form-urlencoded”, strings.NewReader(“..=...”))

defer resp.Body.Close()

body,err:=ioutil.ReadAll(resp.Body)

fmt.Println(string(body))

6.4 正则表达式

Go语言标准库内建提供了regexp包

.   匹配除换行符以外的任意字符
\w  匹配字母或数字或下划线或汉字
\s  匹配任意的空白符
\d  匹配数字
\b  匹配单词的开始或结束
^   匹配字符串的开始
$   匹配字符串的结束
*   重复零次或更多次
+   重复一次或更多次
?   重复零次或一次
{n}     重复n次
{n,}    重复n次或更多次
{n,m}   重复n到m次
捕获 (exp)    匹配exp,并捕获文本到自动命名的组里

(?<name>exp)    匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)

(?:exp)         匹配exp,不捕获匹配的文本,也不给此分组分配组号
func Match(pattern string, b []byte) (matched bool, err error)
func MatchString(pattern string, s string) (matched bool, err error)
func MustCompile(str string) *Regexp
func (re *Regexp) FindAllString(s string, n int) []string
https://my.oschina.net/kuerant/blog/199146

6.5 mysql编程

  1. mysql驱动
    https://github.com/Go-SQL-Driver/MySQL

  2. sqlx
    • database, err := sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/test")
    • r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
    • err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
    • _, err := Db.Exec("update person set username=? where user_id=?", "stu0001", 1)
    • _, err := Db.Exec("delete from person where user_id=?", 1)

6.6 beego框架

beego.me

beego框架之请求数据处理

  • ``符号,表示里面的不用转义
  • 直接解析到struct
    • c.ParseForm(&u)
  • 获取request body里的内容
      1. 在配置文件里设置 copyrequestbody = true
      1. this.Ctx.Input.RequestBody

有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:PowerMichael

查看原文:go语言基础知识汇总

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1456 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传