2. 流程控制 与 函数 |《 刻意学习 Golang 》

golang

起源:学习 golang 笔记,看到 @Summer 的刻意练习、每日精进后,收益匪浅。编程就是需要刻意练习。坚持用此方法把 golang 看完。
书写思路说明:对比 php,理解 Go 的特性,然后代码示例加深理解,并进行刻意的练习达到精进

Go 基础

流程控制和函数

Go 中流程控制有三大类:条件判断、循环控制、无条件跳转

  • if
  • goto
  • for
  • switch

if

  • 不需要()
  • 允许声明变量「作用域只在条件逻辑内」
if a > b {
    //
} else {
    //
}
// 声明变量
if x := computedValue(); x > 10 {
    fmt.Println("x is greater than 10")
} else {
    fmt.Println("x is less than 10")
}
// 多个条件
if a > 4 {
    //
} else if a < 5 {
    //
} else {
    //
}

goto

跳转到必须在当前函数定义的标签

func myFunc() {
    i := 0
Hear:   // 这行的第一个词,以冒号结束作为标签
    fmt.Println(i)
    i++
    goto Hear   // 跳转到 Hear 去「大小写敏感」
}

for

go 中的 for 的三大用处

  • 循环读取数据map slice = php 的 foreach
  • while 来控制逻辑 = php 的 while
  • 迭代操作 = php 的 for
// foreach
for k, v := range map {
    fmt.Println("map's key is ", k)
    fmt.Println("map's value is ", v)
}
//由于 Go 支持 “多值返回”, 而对于“声明而未被调用”的变量, 编译器会报错, 在这种情况下, 可以使用 _ 来丢弃不需要的返回值
for _, v := range map {
    //
}
// while
sum := 1
for sum < 100 {
    sum += sum
}
// for
sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

switch

与 Php 比较

  • case 的数据类型必须一致
  • 表达式不必是常量或者整数,可以没有表达式就找 true
  • 自带 break
  • 支持多值聚合在一个 case 里面
  • fallthrough 强制执行下一个 case
  • case 里面不能有重复条件
i := 10
switch i {
case 10:
    fmt.Println("i match 10")
    fallthrough // 强制执行下一个 case
case i*2 - 10:
    fmt.Println("表达式")
    fallthrough
case 1, 2, 3: // 不能有重复条件 如果有 10 就会报错
    fmt.Println("多值聚合 i is 1 2 or 10")
    fallthrough
case i == 10:
    fmt.Println("bool 类型会报错")
    fallthrough
case 4:
    fmt.Println("默认就有 break 的")
    default:
    fmt.Println("default")
}

函数

与 Php 不一样的地方

  • 关键字 func
  • 参数 & 返回值需要指定类型 name type
  • 多返回值
  • 变参
// 多返回值1 参数相同类型可以简写
func sumAndProduct(a, b int) (int, int) {
    return a + b, a * b
}
// 多返回值2
func sumAndProduct(a int, b int) (sum int, product int) {
    sum = a + b
    product = a * b
    return
}
// 变参
func myfunc(arg ...int) {
    for _, n := range arg { // arg 是一个int 的 slice

    }
}

传值与传指针

PHP 一样,传值是传值的 copy, & 传地址。\
不同的是:\
channel,slice,map这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针

defer

Php 中没有

作用:defer 后指定的函数会在函数退出前调用。多个 defer 调用顺序后进后出「栈」

func ReadWrite() bool {
    file.Open("file")
    defer file.close() // 函数退出前这里会被调用执行
    if FailureX {
        return false
    }
    return true
}

函数作为值类型

函数当做值来传递

  • 声明函数类型 = 定义数据类型
  • 实现函数类型 = 实现数据类型
  • 通过类型跟函数名 = 声明一个变量
type testInt func(int) bool // 声明类型
// 类型的实现
func isTwo(integer int) bool {
    if (integer % 2) {
        return true
    }
    return false
}
// 类型的实现
func isFive(integer int) bool {
    if (integer % 5) {
        return true
    }
    return false
}
// 声明参数函数类型
func filter(slice []int, f testInt) []int {
    var result = []int
    for _, value := range slice {
        if f(value) {
            result = append(result, value)
        }
    }
    return result
}

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println("slice = ", slice)
    two := filter(slice, isTwo)
    five := filter(slice, isFive)
    fmt.Println("倍 2 整除的:", two)
    fmt.Println("被 5 整除的:", five)
}

Panic 和 Recover

Go 没有 try catch \
用的 Panic Recover

  • Panic 中断流程,并退出,延时函数继续执行
  • Recover 可以捕获 Panic 中的参数

main 函数和 init 函数

引用图片

import

与 PHP 对比 \
类似于 include require

  • 绝对路径 相对于 GOROOT 目录
  • 相对路径跟 PHP 一样,但不推荐使用
  • . 操作
  • 别名操作:顾名思义
  • _ 操作:不导入包而是调用包的 init()
// . 操作 可以省略前缀的包名
import (
    . "fmt"
)
fmt.Println("hello world") 可以省略的写成 Println("hello world")
// 别名
import f "fmt"
f.Println("hello world")

高度自律,深度思考,以勤补拙

讨论数量: 7

go里面怎么定义一个含义数字和字符串的数组,比如PHP里$arr=['a',1,2]

2个月前

@lovecn PHP 的数组在 go 里面是 array + slice + map,php 的数组式 hashTable 空间换时间,纠正一下 go 的 map 也是 hashTable 只是有些区别,slice + map 得到的都是一个指针,map 的 key 可以是 string 类型

2个月前

@lovecn 没注意看。 要数字和字符串,arr := map[string]int{"a":1, "1":2, "2":3} 这样的话访问就得是 arr["1"] 并不是真正意义上的数值。我觉得 go 在这里应该是不支持的,PHP 为了实现类型通用,费了不少功夫,也额外需要很大内存开销,go 只比 c 慢 20% 左右,对内存管理应该很严格。PS 没看过 go 的源码。但是 go 的 struct 自己可以去写一个来实现 :joy:

2个月前
Ali

匿名函数貌似跟 PHP 基本一样的写法.

op := func(x, y int) int {
        return x + y
    }
2个月前

@Ali dui,基本一样 :+1: , 我这里落下闭包跟匿名函数。

2个月前
Ali

@jerrkill 修改一下补上呗.👍

2个月前

@jerrkill defer 是先进后出吧

1个月前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!