• go 从入门到了解


    一,GO的安装与配置

    官网:https://golang.org/dl/

    镜像:https://golang.google.cn/dl/

    1,GOPATH

    GOPATH在windows上的默认值:%USERPROFILE%/go

    Go1.14及之后的版本中启用了Go Module模式之后,不一定非要将代码写到GOPATH目录下,所以也就不需要我们再自己配置GOPATH了

    Go1.14之前的版本GOPATH 即为工作目录:本示例设置为 E:workgo

    workgo                  // my-go为GOPATH目录
      -- bin
         -- myApp1        // 编译生成
         -- myApp2        // 编译生成
         -- myApp3        // 编译生成
      -- pkg                  // 依赖包,编译后的归档文件
      -- src
         -- MyApp1        // 项目1
            -- models
            -- controllers
            -- others
            -- main.go 
         -- MyApp2        // 项目2
            -- models
            -- controllers
            -- others
            -- main.go 

    2,Proxy

    2.1,设置代码

    默认GoPROXY配置是:GOPROXY=https://proxy.golang.org,direct,
    https://proxy.golang.org访问不是很可靠,常用的两个代理镜像:
    代理一:go env -w GOPROXY=https://goproxy.io,direct
    代理二:go env -w GOPROXY=https://goproxy.cn,direct

    2.2,设置私仓库

    私有库设置,不走代理
    go env -w GOPRIVATE=*.gitlab.com,*.gitee.com

    2.3,验证包的有效性

    go mod vendor,验证包的有效性时,Get https://sum.golang.org/lookup/xxxxxx: dial tcp 216.58.200.49:443: i/o timeout
    是因为 sum.golang.org 网站不能访问,可以关闭验证包的有效性
    go env -w GOSUMDB=off
    也可以使用国内的网站验证包的有效性
    go env -w GOSUMDB="sum.golang.google.cn"

    3,go环境的常用命令:

    go run src/main.go

    go build src/main.go

    ./main.exe

    go version

    go env 

    3,项目目录结构

    4,开发工具:

    4.1,GoLand (关键在于怎么长期使用)

    GoLand 下载地址:https://www.jetbrains.com/go/download/other.html

    4.2,VS Code

    Vs Code 下载地址:https://code.visualstudio.com/Download

    Ctrl + Shift + P  安装 go:install  相关命令

    5,包管理

    1.5版本之前,依赖包放在GOPATH下
    1.5版本及之后,采用了vendor机制,主要解决包的版本管理
    1.9版本推出了包管理工具,dep
    1.11版本推出了包管理工具,modules 简称 mod

    初始化一个项目的mod, go mod init <项目名>
    go.mod定义:

    module用来定义包名
    require用来定义依赖包及版本
    indirect表示间接引用
    在goland中可以用alt+enter来下载依赖包

    同一个项目的包引用:
    "xcj.com/gose01/src/mypackage"
    不同项目的包引用:
    a,在go.mod里定义:
    require "xcj.com/gose02" v0.0.0
    replace "xcj.com/gose02" => "../gose02"
    b,在使用的文件里定义:
    "xcj.com/gose02/src/testpackage"



    指定安装某个版本:go get package@version
    例:go get github.com/astaxie/beego@v1.11.1

     跨平台编译:

    winows下编译linux可执行文件:
    SET CGO_ENABLED=0 // 禁用CGO
    SET GOOS=linux // 目标平台是linux
    SET GOARCH=amd64 // 目标处理器架构是amd64

    windows下编译苹果可执行文件:
    SET CGO_ENABLED=0
    SET GOOS=darwin
    SET GOARCH=amd64

    变量声明:

    var name string
    var age int
    var isOk bool

    var (
    a string
    b int
    c bool = true
    d float32
    ) // 通过用小括号包含的方式写到多行
    var a, b, c int // 变量a、b、c的类型都是int 若不赋值,用零值来初始化
    var x, y, z = true, 10.24, "randy" // 推导出变量x、y、z的类型分别为bool、float64、string
    var f, err = os.Open(name) // 调用os.Open函数返回一个打开的文件和一个错误信息
    短变量:
    i, j := 0, 1 // 简短声明一组变量,用于函数内部
    a,b: = 200,"hello" // 简短声明一组变量,用于函数内部

    匿名变量:

    定义:
    func Foo(str string) (int, string) {
    return 10, str
    }
    调用:
    x, _ := mypackage.Foo("xcj")
    _, y := mypackage.Foo("yy")
    fmt.Println("x=", x)
    fmt.Println("y=", y)

    // iota是go语言的常量计数器,只能在常量的表达式中使用
    // iota的行记数,只在当前const内生效
    // iota在const关键字出现时将被重置为0 ,主要是用于定义枚举
    // const同时声明多个常量时,如果省略了值则表示和上面一行的值相同
    const (
    n1 = iota
    n2 = iota
    n3 = 0
    n4
    )
    const n5 = iota //0

    fmt.Println(n1,n2,n3,n4,n5)     // 输出结果  0 1 0 0 0

    格式化输出:

    var people interface{} = struct {
    name string
    age int
    }{"sam", 20}
    fmt.Printf("%v ",people) // %v 相应值的默认格式 {sam 20}
    fmt.Printf("%+v ",people) // %+v 打印结构体时,会添加字段名 {name:sam age:20}
    fmt.Printf("%#v ",people) // %#v 相应值的Go语法表示 struct { name string; age int }{name:"sam", age:20}
    fmt.Printf("%T ",people) // %T 相应值的类型的Go语法表示 struct { name string; age int }
    fmt.Printf("%v%% ",100) // %% 字面上的百分号,并非值的占位符 100%

    go的数据类型:

    除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。

    nil是预定义的标识符,代表指针、通道、函数、接口、映射或切片的零值,是预定义好的一个变量

    // 浮点数不是一种精确的表达方式
    x := 0.1
    y := 0.2

    res := x + y
    fmt.Println(res) // 0.30000000000000004
    fmt.Println(res == 0.3) // false

    数组与切片:

    切片可以理解成一种特殊的数组,切片可以改变存储大小,数组是值拷贝而切片是引用 

    // 切片添加值
    //var slice []int = []int{3, 6}
    //fmt.Println(slice)
    //slice = append(slice, 1, 2, 3, 5, 8)
    //fmt.Println(slice)

    fmt.Println("数组***********************************")
    var arr1 [3]int = [3]int{1, 2, 3}
    var arr2 [3]int = arr1
    fmt.Println(arr1, arr2)
    arr2[0] = 10002
    fmt.Println(arr1, arr2)

    fmt.Println("切片***********************************")
    var slice1 []int = []int{1, 2, 3}
    var slice2 []int = slice1
    fmt.Println(slice1, slice2)
    slice2[0] = 10002
    fmt.Println(slice1, slice2)

    数组的大小是类型的一部分,数组大小不可改变
    var a [4]int=[4]int{1,2,3,4}
    var a =[4]int{1,2,3,4}
    a :=[4]int{1,2,3,4}

    interface{} 类型数组,可以包含任意类型

    让编译器根据初始值的个数自行推断数组的长度
    var numArray = [...]int{1, 2}

    使用指定索引值的方式来初始化数组
    a := [...]int{1: 1, 3: 5}
    fmt.Println(a) // [0 1 0 5]

    多组数组
    a := [...][2]string{
    {"北京", "上海"},
    {"广州", "深圳"},
    {"成都", "重庆"},
    }

    切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针(地址)、切片的长度(len)和切片的容量(cap)。
    var a[9]int = [9]int{0,1,2,3,4,5,6,7,8}
    fmt.Println(a)
    var b[]int = a[1:2] // 使用数组构建切片
    fmt.Println(b)
    fmt.Println(len(b))
    fmt.Println(cap(b))

    a := make([]int, 2, 10)
    fmt.Println(a) //[0 0]
    var b []int = make([]int, 3)

    var citySlice []string
    citySlice = append(citySlice, "北京")

    流程控制:

    // if 用法
    if score := 65; score >= 90 {
    fmt.Println("A")
    } else if score > 75 {
    fmt.Println("B")
    } else {
    fmt.Println("C")
    }

    // for
    // for循环可以通过break、goto、return、panic语句强制退出循环。
    i := 0
    for i < 10 {
    fmt.Println(i)
    i++
    }

    // 循环数组
    //names:=[4]string{"张三","李四","王五"}
    //for i,v:=range names{
    // fmt.Println(i,v)
    //}

    // 循环切片
    //names:=[]string{"张三","李四","王五"}
    //for i,v:=range names{
    // fmt.Println(i,v)
    //}

    // 循环字符串
    //for i,v:=range "hello你好"{
    // fmt.Printf("%d %q ",i,v)
    //}


    // map返回键和值
    //ages:=map[string]int{
    // "张三":20,
    // "李四":30,
    //}
    //for i,v:=range ages{
    // fmt.Println(i,v)
    //}

    fallthrough 语法可以执行满足条件的case的下一个case,无条件执行下一个case(穿透)是为了兼容C语言中的case设计的。
    s := "a"
    switch {
    case s == "a":
    fmt.Println("a")
    fallthrough // 无条件执行下一个case(穿透)
    case s == "b":
    // 上一个条件满足之后会执行这条语句 fallthrough
    fmt.Println("b")
    case s == "c":
    fmt.Println("c")
    default:
    fmt.Println("...")
    }

    goto跳转:

    for i := 0; i < 10; i++ {
    for j := 0; j < 10; j++ {
    if j == 2 {
    // 设置退出标签
    goto breakTag
    }
    fmt.Printf("%v-%v ", i, j)
    }
    }
    return
    // 标签
    breakTag:
    fmt.Println("结束for循环")

    函数作为参数传递:

    x11 :=calc(calc(10,20), calc(20,30))
    print(x11)

    func calc(x, y int) (int) {
    sum := x + y
    return sum
    }

    func intSum(x ...int) int {
    fmt.Println(x) //x是一个切片
    sum := 0
    for _, v := range x {
    sum = sum + v
    }
    return sum
    }

    我们可以使用type关键字来定义一个函数类型
    type calculation func(int, int) int
    func add(x, y int) int {
    return x + y
    }

    func sub(x, y int) int {
    return x - y
    }


    函数作为参数:
    func add(x, y int) int {
    return x + y
    }
    func calc(x, y int, op func(int, int) int) int {
    return op(x, y)
    }

    ret2 := calc(10, 20, add)
    fmt.Println(ret2) //30

    闭包指的是一个函数和与其相关的引用环境组合而成的实体

    func adder() func(int) int {
    var x int
    return func(y int) int {
    x += y
    return x
    }
    }
    func main() {
    var f = adder() // f = func(y int) int{...}
    fmt.Println(f(10)) //10
    fmt.Println(f(20)) //30
    fmt.Println(f(30)) //60

    f1 := adder()
    fmt.Println(f1(40)) //40
    fmt.Println(f1(50)) //90
    }


    defer延迟处理,异步处理,最后被defer的语句,最先被执行。
    fmt.Println("start")
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
    fmt.Println("end")


    start
    end
    3
    2
    1


    Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)
    Go语言中使用&字符放在变量前面对变量进行“取地址”操作。
    int、float、bool、string、array、struct
    *int、*float、*bool、*string、*array、*struct

    //指针取值
    a := 10
    b := &a // 取变量a的地址,将指针保存到b中
    fmt.Printf("type of b:%T ", b) // type of b:*int
    c := *b // 指针取值(根据指针去内存取值)
    fmt.Printf("type of c:%T ", c) //type of c:int
    fmt.Printf("value of c:%v ", c) //value of c:10


    func modify1(x int) {
    x = 100
    }

    func modify2(x *int) {
    *x = 100
    }

    func main() {
    a := 10
    modify1(a)
    fmt.Println(a) // 10
    modify2(&a)
    fmt.Println(a) // 100
    }

    // 结构体名字or结构体中的字段名字首字母大写表示公开的、可以被其他包导入,小写表示私有、仅在定义当前结构体的包中可访问
    // 使用type和struct关键字来定义结构体
    // 方法与函数的区别是, 函数不属于任何类型, 方法属于特定的类型。
    //Person 结构体
    type Person struct {
    name string
    age int8
    }

    //NewPerson 构造函数
    func NewPerson(name string, age int8) *Person {
    return &Person{
    name: name,
    age: age,
    }
    }

    //Dream Person做梦的方法
    func (p Person) Dream() {
    fmt.Printf("%s的梦想是学好GO! ", p.name)
    }

    func main() {
    p1 := NewPerson("路人A", 25)
    p1.Dream()
    }

  • 相关阅读:
    PAT 1123 Is It a Complete AVL Tree
    PAT 1122 Hamiltonian Cycle
    PAT 1121 Damn Single
    PAT 1120 Friend Numbers
    JS数组的sort排序
    [转] jquery操作select(取值,设置选中)
    [转]2013和2014年中国互联网企业100强排行榜
    css 更换浏览器 默认图标
    [转]CSS禁止文字选择
    github 在线 创建文件夹
  • 原文地址:https://www.cnblogs.com/xcj26/p/15412224.html
Copyright © 2020-2023  润新知