Loading

ARTS_1

我的github的repo被picgo上传了一个带*的图片,导致无法clone到windows环境下...今天还没办法修复,明日再修

--已经修复,同时装上了PicGo的rename-file插件,再也不用担心命名问题惹

概述

ARTS 是耗子叔发起的编程挑战:

每周完成一个ARTS: 每周至少做一个 leetcode 的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的技术文章。(也就是 Algorithm、Review、Tip、Share 简称ARTS)

Algorithm & Tips

https://leetcode.cn/problems/n-queens/

原本打算浅浅地做一道简单困难leetcode,结果golang写这个题目真的有点把我恶心到了。golang对于一些常用的东西支持也太差了。

golang的二维slice作为参数在子函数里进行append时发生的问题:

以下的代码按照我的逻辑应该是输出,{{}, {}, {}, {}, {}, {"1", "2"}}的。

image-20220919113019846

结果却是输出:

image-20220919113628841

我十分费解,slice不是引用吗?

一开始我以为是因为append的重新分配内存导致地址改变,所以Add无效。但是当我预留空间之后,Add仍然无效。

后来想了一下, 引用本质上于是一个指针,在Add函数中的append语句是通过传进来的指针进行的,也就是传进来的是一个指针局部变量,那么t = append(t, []string{"1", "2"})这句话相当于是把局部变量的值改变,所以修改无效。

所以正确的修改方式应该是如下:

image-20220919114112418

Comment: 我个人觉得很离谱...说是引用,但是slice的append方法如果要添加元素的话,就必然需要按照 a = append(a, val)的形式,又会因为局部变量的原因导致无效。未免有点过于麻烦了,感觉golang对于这些数值之类的运算,还有数组操作的支持非常的烂,都没有slice的pop,还要自己写一个 a = a[:len(a) - 1]😅。

Tips: Golang的pop()

a = a[:len(a) - 1] //注意是否会越界,如果是在函数里传参调用,注意返回a

以及正常的abs都没有,泛型都出来了能不能加一些有用的函数啊!😅

Tips: Golang的int的abs()

math.Abs(float64(a))  //强转其实效率并不高

还有leetcode的运行用例,全局函数居然是所有用例的全局,不是单组样例的,所以每次都需要清空全局。leetcode就不能把我写的代码整个包在一个新定义的地方吗?😅这样每次都是局部开,我就不用注意初始化了。

Solution:

var ans [][]string

type Point struct {
	X, Y int
}

func check(ck []Point, x, y int) bool {
	for p := range ck {
		if ck[p].X == x || ck[p].Y == y || math.Abs(float64(ck[p].X-x)) == math.Abs(float64(ck[p].Y-y)) {
			return false
		}
	}
	return true
}

func add(res []Point, n int) {
	b := make([]byte, n*n)
	for i := 0; i < n*n; i++ {
		b[i] = '.'
	}
	for i := range res {
		b[res[i].X+res[i].Y*n] = 'Q'
	}
	c := make([]string, 0, n)
	for i := 0; i < n; i++ {
		c = append(c, string(b[i*n:i*n+n]))
	}
	ans = append(ans, c)

}

func find(res []Point, y, n int) {
	if y == n {
		if len(res) == n {
			add(res, n)
		}
		return
	}
	for x := 0; x < n; x++ {
		if check(res, x, y) {
			res = append(res, Point{x, y})
			find(res, y+1, n)
			res = res[:len(res)-1]
		}
	}
}

func solveNQueens(n int) [][]string {
	ans = nil	//初始化全局,append会自动分配内存,nil就可以
	res := make([]Point, 0, n)
	find(res, 0, n)
	return ans
}

Review

https://medium.com/gitconnected/options-pattern-in-golang-9a0384a9d8db

看medium看到了一篇讲golang的Options Pattern的。点进去看了一下,正好是我这段时间看公司源码看不懂的地方。于是就狠狠地看,并觉得这是golang工程里一种很重要的模式,决定review一下。

image-20220921115436232

作者一开始也是看源码,发现了这种options, option, o(opts)这些关键字的模式,发现看不懂。之后看到注释说这个是option pattern,于是就恍然大悟(eureka moment),去看更多关于option pattern的资料。

image-20220921115547132

option pattern的定义是这样的

Option pattern is a functional programming pattern that is used to provide optional arguments to a function that can be used to modify its behavior.

用直白一点的话来讲,就是提供可选择的函数参数,之后通过这个函数参数来调整函数行为。

作者举了一个比较直白的Python例子:

image-20220921115602788

image-20220921115610579

也就是你可以选择传入或者不传入lastName来让函数是否打印lastName。

但是在golang里面,上述方法不大可能实现,因为golang没有默认参数(为了符合golang一种问题只能有一种解决方式)。但是golang有接口和不定长参数,于是golang的option pattern就可以通过不一样的方式去实现。

作者的例子非常好理解。

假设我们有一个server的struct,他有三个参数,如下:

image-20220921120015140

那么我们很明显就能写出,他的New函数:

image-20220921115625459

但是如果我想,timeout和maxConnections是可选的该怎么办呢?

首先,我们定义一个接口:

image-20220921115632432

之后写上这样的函数,规范是以With开头:

image-20220921115640070

我们把这个函数叫做,闭包(closure),我的理解闭包就是,一个函数对象,他捕获了外面的参数。

于是我们就可以改写NewServer:

image-20220921115648536

This design is highly scalable and maintainable, even more so than the optional parameter we see in python. It allows us to add more options without bloating our function signature and without touching our code in the factory method.

Share

https://www.cnblogs.com/chanshuyi/p/take_about_my_java_tech_system.html

为了找一篇share花了很多时间,一直都在看无人驾驶、计算机科学与技术前沿还有github上最受欢迎的repo。仔细想想,其实科普类文章或者集思广益的话题在share模块分享也没有不可。

不过最后还是找了一篇算是技术文章的文章把。

ps: 讲道理,需要有自己的观点,还要带有思考,还得是技术类文章,有点难找的。

这篇文章,是作者对自己技术知识框架的一个总结,看了他的总结,其实我是有一点看不到以后的路的感觉的。程序员这行,就是在不断学习新技术,学习新框架的过程,但是一旦一些新的框架,新的技术出来,你学不会,你就会被会的人所淘汰掉。这可能就是大多“35岁”的原因吧。

但是我很怀疑,我并不是很快能掌握一门技术的人,而且不怎么用的话我也会比较快的遗忘。这种一直让我去学的,我真的能做的好吗?

路漫漫,学无涯而生有涯。如果有学完了就一辈子无忧的技术就好了。

posted @ 2022-09-21 11:58  ViKyanite  阅读(48)  评论(1编辑  收藏  举报