Golang命名规范:如何区分N和n
Golang命名规范:如何区分N和n 你好,
我正在编写一个用于分层抽样相关调查的包。在所有相关公式中,使用了以下统计特征:
N表示总体大小n表示从总体中抽取的样本大小Nh表示第h层的规模nh表示从第h层抽取的样本大小
我曾用其他几种语言编写过类似的程序,并且总是使用相应的命名约定来表示上述特征:
N对应N(一个整数)n对应n(一个整数)N_h对应Nh(一个切片)n_h对应nh(一个切片)
对于了解分层抽样(算法核心)的人来说,这就像太阳一样清晰。现在,在 Go 中该如何处理呢?我不能使用小写的 n,但我必须区分 n 和 N。我可以使用 PopulationN 和 SampleN,尽管这有点冗长。但是如何区分切片 N_h 和 n_h 呢?我不应该使用下划线,所以我可能会用 PopulationNh 和 SampleNh,尽管两者都以大写 N 开头,而所有公式都明确区分了 N(表示总体大小)和 n(表示样本大小)。
我从事这方面工作已经超过15年了,我认为使用以下四个变量名应该没问题:PopulationN、SampleN、PopulationNh 和 SampleNh,但它们读起来不自然,这是我第一次遇到语言的命名约定让变量名听起来不自然的情况。
也许用 PopNh 和 SampNh?读起来也不好。那么用 PNh 和 Snh 呢?不行,这也不行:P 代表比例,S 代表标准差(我指的是相应的公式,而不仅仅是统计学的一般概念)。因此,我认为我应该使用更长的名字,尽管最短的版本有一个优点:我区分了大写和小写的“n”,这代表了统计公式中的实际名称。但我不认为这在 PopulationNh 和 Samplenh 中会奏效,因为它们读起来不好。除非我用 Population_Nh 和 Sample_nh……?但这就像重复传递相同的信息,因此前缀(Population_ 和 Sample_)是冗余的,它们的存在仅仅是因为我不能以一个小写字母开始变量名。
有没有什么情况下我可以打破 Go 的命名约定,比如不使用下划线?或者你有一些想法,可以让这些特定的名字更好?我理解这是一个特殊情况,因为我需要在 Go 中找到公式的表示方法,其中 n 与 N 不同,而我在 Go 中无法直接做到这一点。
当然,我可以使用各种名字,如上所述,但我总是非常注意良好的命名,既要能很好地代表现象(这里是统计公式),同时又要读起来顺畅。
嗯,最后一个想法:也许 _Nh 和 _nh 可以?
更多关于Golang命名规范:如何区分N和n的实战教程也可以访问 https://www.itying.com/category-94-b0.html
不,遗憾的是,那个小写的 nh 字段并未导出。
更多关于Golang命名规范:如何区分N和n的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
它们不是常量,而是切片。它们都将构成结构体的字段,但两者都需要被导出,因此都需要以大写字母开头。
简短的回答是你不能。我试图为你寻找替代方案。在任何情况下,你都不能拥有已导出的、小写字母开头的字段。
请原谅,我对“与分层相关的抽样内容”一点也不熟悉,所以对此有点不清楚。使用 Nh 和 nh 有什么问题吗?这些是包级常量吗?
哎呀。但这正是我提出问题的来源和背景:我需要同时导出 Nh 和 nh,这就导致了所有的问题。否则我直接使用它们就行了,但我确实需要同时导出这两个变量。
谢谢。我需要好好考虑一下,或者更确切地说,尝试一下这个方法是否如预期般有效。但目前看来,这似乎是个相当不错的想法。谢谢!我会尝试实践一下,稍后再回来分享我的经验。
难道你不能将你的 Sample.nh 字段直接命名为 Sample.Nh 吗?我知道这可能会造成混淆,但由于它是名为“Sample”的结构体上的一个字段,这是否足以表明你指的是样本的 nh 而非总体的 Nh?
我明白你之前说过了;抱歉。现在懂了!
你是否需要修改这些切片?那么对于返回多个值的函数呢?
type S struct {
vars struct {
Nh []int
nh []int
}
}
func (s *S) Nhnh() (Nh, nh []int) {
return s.vars.Nh, s.vars.nh
}
嗯,这就是生活 😉。所以,显然我必须想出点什么。那些冗长的名字并不好,所以我可能需要想出一个更好的解决方案。如果失败了,我就只能使用它们了。
我还有一个想法,也许不完美,但或许不错。我在考虑无论如何都使用 nh 和相关字段(以小写字母开头),因为它们会在计算中被大量使用,并且应该能很好地代表统计公式中的对应部分——但不需要导出它们,因为所有计算都是在内部完成的。一旦推导出最终解决方案,我会将这些小写字段(如 nh)的最优值赋值给另一个结构体(例如 FinalSolution),该结构体将包含最终的分层结果。在这个结构体中,我会使用冗长的字段名,因为不再需要让它反映任何公式。我并不是说这是理想的解决方案,但它会使用能很好代表相应统计公式的名称。
我认为这个问题很好地表明,人们确实需要花很多心思在代码设计上。也许这对你来说是家常便饭,但我习惯于使用 Python 和 R,它们的命名似乎更简单。但这种简单性常常会导致相当糟糕的名字,如果一个人不太注意命名,只是想到什么就用什么的话。Go 的命名约定不鼓励使用长名字(而我本人喜欢描述性的名字),因此需要仔细斟酌使用哪些名字,这是一件好事,可以极大地提升代码设计。
nh
FinalSolution
再次感谢你,Sean。以下是我的做法(初步方案,后续效果有待观察):
type Stratification struct {
Stratum []int // 层分配(长度为N)
Nh []int // 各层规模
Wh []int // 各层权重
Sh []float64 // 各层标准差
OptFun float64 // 优化函数值
Conditions bool // 分层是否满足所有条件?
Population // 总体表示
Sample // 给定分层下的样本表示
}
type Population struct {
X []float64 // 辅助变量
N int // 总体规模
L int // 层数
Mean float64 // X的总体均值
}
type Sample struct {
n int // 预设总样本量
cv float64 // 预设变异系数
nh []int // 各层样本量
}
(我使用了三个结构体,因为它们分别对应待解决问题的不同部分。)
根据你的说明,大写字母导出规则不适用于嵌套结构体的字段,对吗?因此,我可以进行如下操作:
var S Stratification
S.nh = []int{5, 6, 7}
即使nh字段以小写字母开头,S.nh仍然会被导出。但若我尝试导入Sample.nh字段,这种方式是否将失效?如有理解错误请指正。
在Go中处理统计公式的命名时,确实需要遵循导出规则,但可以通过结构体和组合来保持清晰性。以下是一个示例实现:
package sampling
// Stratified 表示分层抽样的核心参数
type Stratified struct {
PopulationN int // 总体大小
SampleN int // 样本大小
PopulationNh []int // 各层总体大小
SampleNh []int // 各层样本大小
}
// NewStratified 创建分层抽样参数
func NewStratified(popN, sampN int, popNh, sampNh []int) *Stratified {
return &Stratified{
PopulationN: popN,
SampleN: sampN,
PopulationNh: popNh,
SampleNh: sampNh,
}
}
// 内部计算可以使用短变量名
func (s *Stratified) calculate() float64 {
// 在方法内部可以自由使用公式中的原始符号
N := s.PopulationN
n := s.SampleN
Nh := s.PopulationNh
nh := s.SampleNh
// 示例计算:加权平均
var sum float64
for i := range Nh {
sum += float64(nh[i]) / float64(Nh[i])
}
return sum / float64(n) * float64(N)
}
对于包内部使用,可以创建非导出类型:
// internalSampling 内部实现使用短名称
type internalSampling struct {
N int // 总体大小
n int // 样本大小
Nh []int // 各层总体大小
nh []int // 各层样本大小
}
// 导出的包装器
type ExportedSampling struct {
inner internalSampling
}
func (es *ExportedSampling) PopulationN() int {
return es.inner.N
}
func (es *ExportedSampling) SampleN() int {
return es.inner.n
}
另一种方法是使用常量风格:
const (
N = "population"
n = "sample"
Nh = "stratum_population"
nh = "stratum_sample"
)
type Parameters struct {
PopulationSize int
SampleSize int
StratumPopulations []int
StratumSamples []int
}
在测试中可以直接使用短变量名:
func TestStratifiedSampling(t *testing.T) {
// 测试代码中可以使用公式原始符号
N := 1000
n := 100
Nh := []int{300, 400, 300}
nh := []int{30, 40, 30}
// ... 测试逻辑
}
对于公式密集的代码区域,可以使用局部变量保持可读性:
func (s *Stratified) computeVariance() float64 {
// 临时变量使用公式符号
N := s.PopulationN
n := s.SampleN
Nh := s.PopulationNh
nh := s.SampleNh
// 复杂的公式计算
var total float64
for h := range Nh {
Wh := float64(Nh[h]) / float64(N)
fh := float64(nh[h]) / float64(Nh[h])
total += Wh * Wh * fh * (1 - fh) / float64(nh[h])
}
return total
}

