我已经在这几天打破了这个局面,似乎无法弄明白。也许它显而易见,但我似乎无法发现它。我已经阅读了unicode,UTF-8,UTF-16,规范化等所有基础知识,但无济于事。希望有人能够帮助我...
我正在使用testing/quick
包中的Go Value
函数为我的数据结构中的字段生成随机值,以便为所讨论的结构实现Generator
interface。具体来说,给定Metadata
结构,我已将实现定义如下:
func (m *Metadata) Generate(r *rand.Rand, size int) (value reflect.Value) {
value = reflect.ValueOf(m).Elem()
for i := 0; i < value.NumField(); i++ {
if t, ok := quick.Value(value.Field(i).Type(), r); ok {
value.Field(i).Set(t)
}
}
return
}
现在,这样做,我最终将接收器和返回值设置为随机生成的相应类型的值(接收器中的字符串,整数等,并在返回的反射中反映。值) .value的)。
现在,Value
函数的实现声明它将返回类型[]rune
转换为类型string
的内容。据我所知,这应该允许我使用runes
,unicode
和norm
包中的函数来定义过滤器,过滤掉不属于'Latin','Letter'或'Number'。我定义了以下过滤器,该过滤器使用变换来过滤掉那些不在rangetable
s字符中的字母(如unicode
包中所定义):
func runefilter(in reflect.Value) (out reflect.Value) {
out = in // Make sure you return something
if in.Kind() == reflect.String {
instr := in.String()
t := transform.Chain(norm.NFD, runes.Remove(runes.NotIn(rangetable.Merge(unicode.Letter, unicode.Latin, unicode.Number))), norm.NFC)
outstr, _, _ := transform.String(t, instr)
out = reflect.ValueOf(outstr)
}
return
}
现在,我认为我已经尝试过任何事情,但我最终会得到一系列远离拉丁语范围的字符串,例如:
똿穊
嚶
秓䝏小䮋
ท솲
䂾
ʋᦸ
堮憨ꥆ
併怃
鯮
⓿ꐠ槹黟
踁퓺
俇
쩈詢
欓
那么,任何人都可以解释我在这里忽略的内容以及如何定义transformer
来删除/替换非字母/数字/拉丁字符以便我可以使用Value
函数如预期的那样(但是'随机'字符的子集较小?)
谢谢!
答案 0 :(得分:1)
令人困惑的是,Generate接口需要使用类型而不是指向类型的指针的函数。您希望类型签名看起来像
func (m Metadata) Generate(r *rand.Rand, size int) (value reflect.Value)
您可以使用此here。注意:在该游乐场中最重要的事情是将生成函数的类型从m Metadata
切换到m *Metadata
并看到嗨妈妈!从不打印。
此外,我认为使用您自己的类型并使用您要使用的所有字符列表为该类型编写generate方法会更好。例如:
type LatinString string
const latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01233456789"
然后使用生成器
func (l LatinString) Generate(rand *rand.Rand, size int) reflect.Value {
var buffer bytes.Buffer
for i := 0; i < size; i++ {
buffer.WriteString(string(latin[rand.Intn(len(latin))]))
}
s := LatinString(buffer.String())
return reflect.ValueOf(s)
}
编辑:这个库也很酷,感谢你向我展示
答案 1 :(得分:0)
我自己的问题的答案似乎是@nj_和@jimb评论中提供的答案和@benjaminkadish提供的答案的组合。
简而言之,答案归结为:
Letter || Number || Latin
),而不是'Latin'的交集与'Letter'的 union 和'数字'((Letter || Number) && Latin)
)现在是更长版本......
我使用testing/quick
包后面的想法是我想要随机数据进行代码的(模糊)测试。在过去,我总是一次又一次地编写代码来自己做这样的事情。这意味着不同项目中的许多相同代码。现在,我当然可以为它编写自己的软件包,但事实证明,甚至比这更好,实际上有一个标准软件包可以完全满足我的需求。
现在,事实证明包装完全符合我的要求。它生成的字符串中的代码点实际上是 random ,而不仅限于我们习惯在日常生活中使用的内容。现在,这当然是您在进行模糊测试时想要的,以便使用超出通常假设的值来测试代码。
实际上,这意味着我遇到了两个问题:
Name
字段或URL
字段的处理时,我可以合理地假设不会出现像'JamesMc⌢'这样的值(让单独的'James Mc'或'www.site.com',但只是'James McFrown'和'www.website.com'。因此,我不能指望合理的系统能够支持它。当然,事情不应该完全崩溃,但也不能指望它没有任何问题处理前面的例子。testing/quick
使用的集合中可能的字符集非常大(0x10FFFF),而合理字符的集合如此之小,大多数时候最终会出现空字符串。 那么,我们需要从中汲取什么呢?
所以,虽然我希望使用标准testing/quick
软件包来替换我经常重复的代码来生成模糊测试的随机数据,但它做得很好,它提供的数据超出了我认为合理的范围使代码能够处理。似乎最终的选择是:
Generator
一起使用。这意味着您将不得不在整个代码中使用派生类型而不是基本类型。 (与在C ++中将string
定义为wchar_t
而不是char
并在默认情况下使用testing/quick
相比较。或... 与往常一样,进一步的评论当然是受欢迎的,因为我很可能忽略了一些事情。