独立开发者也需要原型工具

我一开始认为独立开发者是不需要原型工具的。原因有两个,一是原型工具上手需要成本。而独立开发者前端技术比较熟悉,比较容易构建一个原型出来。在这一点上,手绘草图的意义也大于原型工具。二是独立开发不需要沟通,原型做出来也没有意义。

但是在上手原型工具墨刀之后,我发现工具本身也在改变我的认知方式。首先,墨刀上手并不需要多少成本,反倒可以专注产品功能本身,而写代码无论怎样都可能陷入细节。其次分享功能的便利性让我学着去分享自己的创意,然后可以与用户进行沟通,可以在项目前期确定好功能点。

另外通过设计和编码进行分离,在设计和编码阶段都能更好的投入。若混合在一起,往往会因为不知道自己要什么而带来更大的成本。

Gin 路由默认重定向问题

有个问题很诡异,IOS Chrome 版本登陆会显示 401 未授权问题。经过定位,发现表面上是前端路由和后端路由不匹配才会出现。比如前端写着请求地址是 /api/users,后端路由是 /api/users/。但是在 PC 上却没有复现这个问题。PC 上 Chrome 根据 Gin 的 301 重定向到新的地址。IOS 没有办法看到,但是从后端日志看出应该是重定向再次访问的时候,手机浏览器没有带上 token 导致的,好像只是请求体的重定向。具体原因尚不清楚。

Gorm 关联语法解惑

Photo by Lerone Pieters on Unsplash

Gorm 关联语法与我的常识有冲突,导致尝试他的关联语法花了一些时间。最终结果如下

type CrawlResult struct {
	Crawler     Crawler   `gorm:"foreignKey:CrawlerId;references:CrawlerId"`
	CrawlerId   string    `json:"crawlerId" gorm:"column:crawler_id"`
}
type Crawler struct {
	CrawlerId string `gorm:"primaryKey;column:crawler_id"`
}

可以看到,在外键存在的表需要自己设定一个外键,这里是 CrawlerId,同时需要将对应结构体 Crawler 作为属性聚合在其中。这里 foreignKey 是指 CrawlResult 本体结构的属性 CrawlerId,references 指的是 Crawler 的外键。然后你在关联的时候可以直接这样做

db.Preload("Crawler").Find(&results)

这里 Preload 指的是外部结构名称。

总结

内部实体的外键要自己建立,然后用foreignKey关联才行。