GO语言基础 | 青训营笔记

79 阅读3分钟

使用多个变量时,for循环的init和post语句必须使用平行赋值

错误写法:for i := 0, j := len(numbers) - 1; i < j;

func twoSum(numbers []int, target int) []int {
    var result []int
    var sum int = 0
    for i := 0, j := len(numbers) - 1; i < j; {
        sum = numbers[i] + numbers[j]
        if sum == target {
            result = []int{i + 1, j + 1}
            break
        } else if sum > target {
            j--
        } else {
            i++
        }
    }
    return result
}

正确写法:for i, j := 0, len(numbers)-1; i < j;

func twoSum(numbers []int, target int) []int {
	var result []int
	var sum int = 0
	for i, j := 0, len(numbers)-1; i < j; {
		sum = numbers[i] + numbers[j]
		if sum == target {
			result = []int{i + 1, j + 1}
			break
		} else if sum > target {
			j--
		} else {
			i++
		}
	}
	return result
}

return语句写在for循环中会出现missing return的错误

错误写法:

func twoSum(numbers []int, target int) []int {
	var result []int
	var sum int = 0
	for i, j := 0, len(numbers)-1; i < j; {
		sum = numbers[i] + numbers[j]
		if sum == target {
			result = []int{i + 1, j + 1}
			return result
		} else if sum > target {
			j--
		} else {
			i++
		}
	}
}

正确写法:

func twoSum(numbers []int, target int) []int {
	var result []int
	var sum int = 0
	for i, j := 0, len(numbers)-1; i < j; {
		sum = numbers[i] + numbers[j]
		if sum == target {
			result = []int{i + 1, j + 1}
			break
		} else if sum > target {
			j--
		} else {
			i++
		}
	}
	return result
}

出现missing return的解决方案:

1、首先检测程序逻辑,有没有可能出现一些情况会导致程序没有返回值。如果有,则需要修改程序逻辑。

2、如果程序逻辑本身没有问题,但依旧出现此警告,那就是在程序的最后缺少return语句。编译器在编译时不会管if、else if等语句内的return语句,不知道你具体会在哪里返回,这个只有程序运行时才能确定。所以,如果你程序最后没有return语句,编译器就认为你错了,语法不通过。

原文链接:blog.csdn.net/m0_46608503…

String字符串是否可变

String字符串可变语言:

C/C++, Ruby, PHP, Swift

String字符串不可变语言:

Java, Python, C#, Javascript, Go

Goland Debugger不可用问题

结论:Goland版本与Go版本的兼容问题,导致delve工具无法使用

解决方案:更新delve,或者升级Goland(目前Goland 2023.1.1、Go 1.20.1)

猜数游戏例子

  1. 只用rand.Intn每次也可以输出不一样的随机数,不需要通过rand.Seed随机输入种子

  2. 无论输出什么数字,都会判定非法输入

    结论:通过debug知道每个input后会自动添加"\r\n",修改TrimSuffix函数的参数即可

  3. Scanf、Scan与Scanln的区别

    Scanf:按照给定的格式依次读取数据(包括非法数据),不能换行输入(如果要换行需要在前面加一个scanln吸收掉回车符)

    Scan:比scanf高级,依次读取数据,遇到回车会忽略,可以换行输入(如果要先用了scan输入,再用scanf输入的话,需要在中间加一个scanln)

    Scanln:类似scan,但是遇到换行(回车)立马结束输入,如果要换行输入必须用多个scanln

Go的通信机制

两种:通过通信共享内存(提倡,使用channel)、通过共享内存实现通信(使用临界区加锁Lock)

无缓冲通道make(chan int),有缓冲通道make(chan int, 2)

channel、Lock与waitGroup均可以保证并发安全。

Go依赖管理三要素

配置文件描述依赖(go.mod)、中心仓库管理依赖库(Proxy)、本地工具(go get/go mod)

高质量的Go代码

  1. 代码格式

    使用gofmt自动格式化代码

  2. 注释

    解释代码作用what、如何实现how、实现的原因why、出错情况分析

    重点:补充额外的上下文信息

  3. 命名规范

    • 变量variable:缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写

    • 函数function:尽量简短,不要包含包名的信息

    • 包package:全小写,不与标准库同名,使用单数

  4. 控制流程

    避免if-else嵌套,提前处理异常错误情况

  5. 错误和异常处理

    • errors.New表示简单错误,格式化需求使用fmt.Errorf(%w关键字将错误关联至错误链)

    • errors.Is判定一个错误是否为特定错误

    • errors.As在错误链上获取特定种类的错误

    • 不建议用panic,recover只在当前goroutine的defer函数中生效