关于php:go学习笔记1

43次阅读

共计 10003 个字符,预计需要花费 26 分钟才能阅读完成。

hello GO

这里应用 vscode

  1. 装置插件 go
  2. 新建 hello 文件夹, 创立 main.go 文件

    package main
    import "fmt"
    func main(){fmt.Println("Hello")
    }
    1. 关上命令行

  3. 执行 go build 这时同目录会创立一个 hello.exe 的文件(我这里应用的是 win 电脑)

    也能够应用 go build -o aaa.exe 指定文件名

也间接输入可应用 go run main.go

跨平台编译

只须要指定指标操作系统的平台和处理器架构即可:

SET CGO_ENABLED=0  // 禁用 CGO
SET GOOS=linux  // 指标平台是 linux
SET GOARCH=amd64  // 指标处理器架构是 amd64

而后再执行 go build 命令,失去的就是可能在 Linux 平台运行的可执行文件了。

Mac 下编译 Linux 和 Windows 平台 64 位 可执行程序:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Linux 下编译 Mac 和 Windows 平台 64 位可执行程序:

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Windows 下编译 Mac 平台 64 位可执行程序:

SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build

根底

// 单行正文

/*

多行正文

*/

fmt.Println(‘ 打印输出 ’)

一行代码不需加分号

变量申明后必须应用, 不应用会报错

缩进没有严格要求

变量和常量

标书与关键字

Go 语言中标识符由字母数字和 _(下划线)组成,并且只能以字母和_ 结尾。

关键词

25 个关键词

   break        default      func         interface    select
    case         defer        go           map          struct
    chan         else         goto         package      switch
    const        fallthrough  if           range        type
    continue     for          import       return       var

37 个保留词

    Constants:    true  false  iota  nil

           Types:    int  int8  int16  int32  int64  
                  uint  uint8  uint16  uint32  uint64  uintptr
                  float32  float64  complex128  complex64
                  bool  byte  rune  string  error

    Functions:   make  len  cap  new  append  copy  close  delete
                 complex  real  imag
                 panic  recover

变量

申明: var 变量名 变量类型

单个申明
var aaa string
var age int
var iss bool

批量申明
var (
    a string
    b int
    c bool
)

变量初始化: var 变量名 类型 = 表达式

var name string = "aa"

一次初始化多个变量
var name,age = "bb",20

短变量申明(申明并初始化) :=

n:=10
m:=50

匿名变量: 用一个下划线 _ 示意

匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在反复申明。(在 Lua 等编程语言里,匿名变量也被叫做哑元变量。)

func foo() (int, string) {return 10, "Q1mi"}
func main() {x, _ := foo()
    _, y := foo()
    fmt.Println("x=", x)
    fmt.Println("y=", y)
}

留神:

函数外的每个语句都必须以关键字开始(var、const、func 等)

:=不能应用在函数外。

_多用于占位,示意疏忽值。

常量 const

const a = 'dsadasd'

和变量相似

const (
    a string
    b int
    c bool
)

iota : go 语言的常量计数器

iota在 const 关键字呈现时将被重置为 0

const (
        n1 = iota //0
        n2        //1
        n3        //2
        n4        //3
    )

应用_调过某些值
const (
        n1 = iota //0
        n2        //1
        _
        n4        //3
    )    

iota申明两头插队

const (
        n1 = iota //0
        n2 = 100  //100
        n3 = iota //2
        n4        //3
    )
    const n5 = iota //0

多个 iota 定义在一行

const (
        a, b = iota + 1, iota + 2 //1,2
        c, d                      //2,3
        e, f                      //3,4
    )

数据类型

整型

Go 语言中有丰盛的数据类型,除了根本的整型、浮点型、布尔型、字符串外,还有数组、切片、构造体、函数、map、通道(channel)等。

类型 形容
uint8 无符号 8 位整型 (0 到 255)
uint16 无符号 16 位整型 (0 到 65535)
uint32 无符号 32 位整型 (0 到 4294967295)
uint64 无符号 64 位整型 (0 到 18446744073709551615)
int8 有符号 8 位整型 (-128 到 127)
int16 有符号 16 位整型 (-32768 到 32767)
int32 有符号 32 位整型 (-2147483648 到 2147483647)
int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

非凡整型

类型 形容
uint 32 位操作系统上就是uint32,64 位操作系统上就是uint64
int 32 位操作系统上就是int32,64 位操作系统上就是int64
uintptr 无符号整型,用于寄存一个指针

进制

    // 十进制
    var a int = 10
    fmt.Printf("%d \n", a)  // 10
    fmt.Printf("%b \n", a)  // 1010  占位符 %b 示意二进制
 
    // 八进制  以 0 结尾
    var b int = 077
    fmt.Printf("%o \n", b)  // 77
 
    // 十六进制  以 0x 结尾
    var c int = 0xff
    fmt.Printf("%x \n", c)  // ff
    fmt.Printf("%X \n", c)  // FF

浮点型

Go 语言反对两种浮点型数:float32float64

package main
import (
        "fmt"
        "math"
)
func main() {fmt.Printf("%f\n", math.Pi)
        fmt.Printf("%.2f\n", math.Pi)
}

复数

complex64 和 complex128

复数有实部和虚部,complex64 的实部和虚部为 32 位,complex128 的实部和虚部为 64 位。

var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Println(c1)
fmt.Println(c2)

布尔值

Go 语言中以 bool 类型进行申明布尔型数据,布尔型数据只有 true(真)false(假)两个值。

留神:

  1. 布尔类型变量的默认值为false
  2. Go 语言中不容许将整型强制转换为布尔型.
  3. 布尔型无奈参加数值运算,也无奈与其余类型进行转换。

字符串

s1 := "hello"
s2 := "你好"

字符串本义符

本义符 含意
\r 回车符(返回行首)
\n 换行符(间接跳到下一行的同列地位)
\t 制表符
\' 单引号
\" 双引号
\\ 反斜杠

多行字符串 应用反引号

字符串的罕用操作

办法 介绍
len(str) 求长度
+ 或 fmt.Sprintf 拼接字符串
strings.Split 宰割
strings.contains 判断是否蕴含
strings.HasPrefix,strings.HasSuffix 前缀 / 后缀判断
strings.Index(),strings.LastIndex() 子串呈现的地位
strings.Join(a[]string, sep string) join 操作

byte 和 rune 类型

字符用单引号(’)包裹起来

  1. nt8类型,或者叫 byte 型,代表了 ASCII 码 的一个字符。
  2. rune类型,代表一个 UTF- 8 字符

当须要解决中文、日文或者其余复合字符时,则须要用到 rune 类型。rune类型理论是一个int32

批改字符串

要批改字符串,须要先将其转换成 []rune[]byte,实现后再转换为string。无论哪种转换,都会从新分配内存,并复制字节数组。

func changeString() {
    s1 := "big"
    // 强制类型转换
    byteS1 := []byte(s1)
    byteS1[0] = 'p'
    fmt.Println(string(byteS1))

    s2 := "白萝卜"
    runeS2 := []rune(s2)
    runeS2[0] = '红'
    fmt.Println(string(runeS2))
}

类型转换

强制转换

T(表达式)
T 示意要转换的类型。表达式包含变量、简单算子和函数返回值等.

运算符

  1. 算术运算符 + - * / %
  2. 关系运算符 == != > >= < <=
  3. 逻辑运算符 && || !
  4. 位运算符

    运算符 形容
    & 参加运算的两数各对应的二进位相与。(两位均为 1 才为 1)
    \ 参加运算的两数各对应的二进位相或。(两位有一个为 1 就为 1)
    ^ 参加运算的两数各对应的二进位相异或,当两对应的二进位相异时,后果为 1。(两位不一样则为 1)
    << 左移 n 位就是乘以 2 的 n 次方。“a<<b”是把 a 的各二进位全副左移 b 位,高位抛弃,低位补 0。
    >> 右移 n 位就是除以 2 的 n 次方。“a>>b”是把 a 的各二进位全副右移 b 位。
  5. 赋值运算符 = += -= *= /= %= <<= >>= &= |= ^=

流程管制

ifelse

if 表达式 1 {分支 1} else if 表达式 2 {分支 2} else{分支 3}

for

for 初始语句; 条件表达式; 完结语句{循环体语句}
残缺
func forDemo() {
    for i := 0; i < 10; i++ {fmt.Println(i)
    }
}
初始语句省略
func forDemo2() {
    i := 0
    for ; i < 10; i++ {fmt.Println(i)
    }
}
初始语句 / 完结语句完结
func forDemo3() {
    i := 0
    for i < 10 {fmt.Println(i)
        i++
    }
}
有限循环
for {循环体语句}

for range(键值循环)

switch case

func switchDemo1() {
    finger := 3
    switch finger {
    case 1:
        fmt.Println("大拇指")
    case 2:
        fmt.Println("食指")
    case 3:
        fmt.Println("中指")
    case 4:
        fmt.Println("无名指")
    case 5:
        fmt.Println("小拇指")
    default:
        fmt.Println("有效的输出!")
    }
}
func testSwitch3() {
    switch n := 7; n {
    case 1, 3, 5, 7, 9:
        fmt.Println("奇数")
    case 2, 4, 6, 8:
        fmt.Println("偶数")
    default:
        fmt.Println(n)
    }
}

fallthrough语法能够执行满足条件的 case 的下一个 case,是为了兼容 C 语言中的 case 设计的。

func switchDemo5() {
    s := "a"
    switch {
    case s == "a":
        fmt.Println("a")
        fallthrough
    case s == "b":
        fmt.Println("b")
    case s == "c":
        fmt.Println("c")
    default:
        fmt.Println("...")
    }
}
输入:
a
b

goto

通过标签进行代码间的无条件跳转

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

break(跳出循环)

break语句能够完结 forswitchselect的代码块。

func breakDemo1() {
BREAKDEMO1:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if j == 2 {break BREAKDEMO1}
            fmt.Printf("%v-%v\n", i, j)
        }
    }
    fmt.Println("...")
}

continue(持续下次循环)

func continueDemo() {
forloop1:
    for i := 0; i < 5; i++ {
        // forloop2:
        for j := 0; j < 5; j++ {
            if i == 2 && j == 2 {continue forloop1}
            fmt.Printf("%v-%v\n", i, j)
        }
    }
}

数组

数组定义

var 数组变量名 [元素数量]T

一旦定义,长度不能变

初始化
func main() {var testArray [3]int                        // 数组会初始化为 int 类型的零值
    var numArray = [3]int{1, 2}                 // 应用指定的初始值实现初始化
    var cityArray = [3]string{"北京", "上海", "深圳"} // 应用指定的初始值实现初始化
    fmt.Println(testArray)                      //[0 0 0]
    fmt.Println(numArray)                       //[1 2 0]
    fmt.Println(cityArray)                      //[北京 上海 深圳]
}
func main() {var testArray [3]int
    var numArray = [...]int{1, 2}
    var cityArray = [...]string{"北京", "上海", "深圳"}
    fmt.Println(testArray)                          //[0 0 0]
    fmt.Println(numArray)                           //[1 2]
    fmt.Printf("type of numArray:%T\n", numArray)   //type of numArray:[2]int
    fmt.Println(cityArray)                          //[北京 上海 深圳]
    fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string
}
func main() {a := [...]int{1: 1, 3: 5}
    fmt.Println(a)                  // [0 1 0 5]
    fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}
数组遍历
func main() {var a = [...]string{"北京", "上海", "深圳"}
    // 办法 1:for 循环遍历
    for i := 0; i < len(a); i++ {fmt.Println(a[i])
    }

    // 办法 2:for range 遍历
    for index, value := range a {fmt.Println(index, value)
    }
}
多维数组
func main() {a := [3][2]string{{"北京", "上海"},
        {"广州", "深圳"},
        {"成都", "重庆"},
    }
    for _, v1 := range a {
        for _, v2 := range v1 {fmt.Printf("%s\t", v2)
        }
        fmt.Println()}
}

北京    上海    
广州    深圳    
成都    重庆

多维数组 只有第一层 能够应用 ... 来让编译器推导数组长度。例如:

// 反对的写法
a := [...][2]string{{"北京", "上海"},
    {"广州", "深圳"},
    {"成都", "重庆"},
}
// 不反对多维数组的内层应用...
b := [3][...]string{{"北京", "上海"},
    {"广州", "深圳"},
    {"成都", "重庆"},
}
数组是值类型

数组是值类型,赋值和传参会复制整个数组。因而扭转正本的值,不会扭转自身的值。

func modifyArray(x [3]int) {x[0] = 100
}

func modifyArray2(x [3][2]int) {x[2][0] = 100
}
func main() {a := [3]int{10, 20, 30}
    modifyArray(a) // 在 modify 中批改的是 a 的正本 x
    fmt.Println(a) //[10 20 30]
    b := [3][2]int{{1, 1},
        {1, 1},
        {1, 1},
    }
    modifyArray2(b) // 在 modify 中批改的是 b 的正本 x
    fmt.Println(b)  //[[1 1] [1 1] [1 1]]
}

留神:

  1. 数组反对“==“、”!=”操作符,因为内存总是被初始化过的。
  2. [n]*T示意指针数组,*[n]T示意数组指针。

切片

一个领有雷同类型元素的可变长度的序列

定义

var name []T

长度 / 容量

通过应用内置的 len() 函数求长度,应用内置的 cap() 函数求切片的容量

len(s), cap(s)
应用 make()函数创立结构切片
make([]T, size, cap)
T: 切片的元素类型
size: 切片中元素的数量
cap: 切片的容量

a := make([]int, 2, 10)
fmt.Println(a)      //[0 0]
fmt.Println(len(a)) //2
fmt.Println(cap(a)) //10
判断切片是否为空

请始终应用 len(s) == 0 来判断,而不应该应用 s == nil 来判断。

切片不能间接比拟
切片赋值拷贝
s1 := make([]int, 3) //[0 0 0]
    s2 := s1             // 将 s1 间接赋值给 s2,s1 和 s2 共用一个底层数组
切片遍历

遍历形式和数组是统一的

append
func main(){var s []int
    s = append(s, 1)        // [1]
    s = append(s, 2, 3, 4)  // [1 2 3 4]
    s2 := []int{5, 6, 7}  
    s = append(s, s2...)    // [1 2 3 4 5 6 7]
}

var 申明的零值切片能够在 append() 函数间接应用,无需初始化。

s := []int{}  // 没有必要初始化
s = append(s, 1, 2, 3)

var s = make([]int)  // 没有必要初始化
s = append(s, 1, 2, 3)

追加切片

var citySlice []string
// 追加一个元素
citySlice = append(citySlice, "北京")
// 追加多个元素
citySlice = append(citySlice, "上海", "广州", "深圳")
// 追加切片
a := []string{"成都", "重庆"}
citySlice = append(citySlice, a...)
fmt.Println(citySlice) //[北京 上海 广州 深圳 成都 重庆]
copy
copy(destSlice, srcSlice []T)
srcSlice: 数据起源切片
destSlice: 指标切片
func main() {// copy()复制切片
    a := []int{1, 2, 3, 4, 5}
    c := make([]int, 5, 5)
    copy(c, a)     // 应用 copy()函数将切片 a 中的元素复制到切片 c
    fmt.Println(a) //[1 2 3 4 5]
    fmt.Println(c) //[1 2 3 4 5]
    c[0] = 1000
    fmt.Println(a) //[1 2 3 4 5]
    fmt.Println(c) //[1000 2 3 4 5]
}
删除元素

没有删除切片元素的专用办法,咱们能够应用切片自身的个性来删除元素

从切片 a 中删除索引为 index 的元素,操作方法是a = append(a[:index], a[index+1:]...)

func main() {
    // 从切片中删除元素
    a := []int{30, 31, 32, 33, 34, 35, 36, 37}
    // 要删除索引为 2 的元素
    a = append(a[:2], a[3:]...)
    fmt.Println(a) //[30 31 33 34 35 36 37]
}

map

map 定义
map[KeyType]ValueType
KeyType: 示意键的类型。ValueType: 示意键对应的值的类型。

map 类型的变量默认初始值为 nil,须要应用 make()函数来分配内存。语法为:

make(map[KeyType]ValueType, [cap])
根本应用
func main() {scoreMap := make(map[string]int, 8)
    scoreMap["张三"] = 90
    scoreMap["小明"] = 100
    fmt.Println(scoreMap)
    fmt.Println(scoreMap["小明"])
    fmt.Printf("type of a:%T\n", scoreMap)
}

map[小明:100 张三:90]
100
type of a:map[string]int


map 也反对在申明的时候填充元素
func main() {userInfo := map[string]string{
        "username": "沙河小王子",
        "password": "123456",
    }
    fmt.Println(userInfo) //
}
判断某个键是否存在
value, ok := map[key]
func main() {scoreMap := make(map[string]int)
    scoreMap["张三"] = 90
    scoreMap["小明"] = 100
    // 如果 key 存在 ok 为 true,v 为对应的值;不存在 ok 为 false,v 为值类型的零值
    v, ok := scoreMap["张三"]
    if ok {fmt.Println(v)
    } else {fmt.Println("查无此人")
    }
}
map 遍历
func main() {scoreMap := make(map[string]int)
    scoreMap["张三"] = 90
    scoreMap["小明"] = 100
    scoreMap["娜扎"] = 60
    for k, v := range scoreMap {fmt.Println(k, v)
    }
}

遍历 map 时的元素程序与增加键值对的程序无关。

delete
delete(map, key)
func main(){scoreMap := make(map[string]int)
    scoreMap["张三"] = 90
    scoreMap["小明"] = 100
    scoreMap["娜扎"] = 60
    delete(scoreMap, "小明")// 将小明:100 从 map 中删除
    for k,v := range scoreMap{fmt.Println(k, v)
    }
}
依照指定程序遍历 map
func main() {rand.Seed(time.Now().UnixNano()) // 初始化随机数种子

    var scoreMap = make(map[string]int, 200)

    for i := 0; i < 100; i++ {key := fmt.Sprintf("stu%02d", i) // 生成 stu 结尾的字符串
        value := rand.Intn(100)          // 生成 0~99 的随机整数
        scoreMap[key] = value
    }
    // 取出 map 中的所有 key 存入切片 keys
    var keys = make([]string, 0, 200)
    for key := range scoreMap {keys = append(keys, key)
    }
    // 对切片进行排序
    sort.Strings(keys)
    // 依照排序后的 key 遍历 map
    for _, key := range keys {fmt.Println(key, scoreMap[key])
    }
}
元素为 map 类型的切片
func main() {var mapSlice = make([]map[string]string, 3)
    for index, value := range mapSlice {fmt.Printf("index:%d value:%v\n", index, value)
    }
    fmt.Println("after init")
    // 对切片中的 map 元素进行初始化
    mapSlice[0] = make(map[string]string, 10)
    mapSlice[0]["name"] = "小王子"
    mapSlice[0]["password"] = "123456"
    mapSlice[0]["address"] = "沙河"
    for index, value := range mapSlice {fmt.Printf("index:%d value:%v\n", index, value)
    }
}
值为切片类型的 map
func main() {var sliceMap = make(map[string][]string, 3)
    fmt.Println(sliceMap)
    fmt.Println("after init")
    key := "中国"
    value, ok := sliceMap[key]
    if !ok {value = make([]string, 0, 2)
    }
    value = append(value, "北京", "上海")
    sliceMap[key] = value
    fmt.Println(sliceMap)

高颜值后盾管理系统收费应用 ### 子枫后盾管理系统 ###,可在宝塔面板间接装置

欢送关注我的公众号:子枫的微妙世界,取得独家整顿的学习资源和日常干货推送。
如果您对我的其余专题内容感兴趣,中转我的集体博客:www.wangmingchang.com。

正文完
 0