起初我以为go的package就是把一个目录的代码包起来,后来发现我被耍了。go不允许循环依赖。所以一个程序的依赖图,就是一棵以package main为根的树,如果是没有main的库的话就是一个DAG。无论是一颗树还是一个DAG,都肯定可以用拓扑排序排成一个一维数组。也就是说,依赖图只是表象,其本质是一个一维的等级结构。
从现在起我们把package A import package B称作A < B,并应用<的传递关系。
在这个等级结构中,一个package能用所有大于它的package的代码,它自己的代码能被所有小于它的代码使用。也就是说package越大,所能用的package就越少,相反,越能被更多package使用。
当我新建一个package时,我以为我只是把代码包起来,实际上,我需要在这个一维的等级结构中找一个合适的位置去安置这个package,这给了我很大的压力。也许太多package并不是一个好的选择。
我看在这个等级制度下,一个比较常见的结构是,业务逻辑 < 公共逻辑 < 数据结构 < 外部库。把数据结构(各种struct定义)放在最大的位置是为了让它作为协议,能在不同层级之间传来传去。而由于它在最大的位置,它很多库都用不了,所以它很难实现业务逻辑,所以对这些数据结构的操作的逻辑都是写在更小的公共逻辑/业务逻辑层。有人称这种模式为贫血模型。也就是说,是这个一维等级制度选择了贫血模型,充血模型在这里是很难实现的。
我觉得go代码的组织方式就应该是一个文件夹套一个文件夹这样套下去,来体现这个一维结构,常见的平铺文件夹的方式很有迷惑性。当然,这要是在中间插了一个文件夹那要改很多代码,要做个工具来自动搞。