doulaopu2343 2016-07-06 12:10 采纳率: 100%
浏览 100
已采纳

使用Go的“测试/快速”包生成数字和字母的随机字符串

I've been breaking my head over this for a few days now and can't seem to be able to figure it out. Perhaps it's glaringly obvious, but I don't seem to be able to spot it. I've read up on all the basics of unicode, UTF-8, UTF-16, normalisation, etc, but to no avail. Hopefully somebody's able to help me out here...

I'm using Go's Value function from the testing/quick package to generate random values for the fields in my data structs, in order to implement the Generator interface for the structs in question. Specifically, given a Metadata struct, I've defined the implementation as follows:

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
}

Now, in doing so, I'll end up with both the receiver and the return value being set with random generated values of the appropriate type (strings, ints, etc. in the receiver and reflect.Value in the returned reflect.Value).

Now, the implementation for the Value function states that it will return something of type []rune converted to type string. As far as I know, this should allow me to then use the functions in the runes, unicode and norm packages to define a filter which filters out everything which is not part of 'Latin', 'Letter' or 'Number'. I defined the following filter which uses a transform to filter out letters which are not in those character rangetables (as defined in the unicode package):

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
}

Now, I think I've tried just about anything, but I keep ending up with a series of strings which are far from the Latin range, e.g.:

  • 写回答

2条回答 默认 最新

  • doumu1212 2016-07-06 19:37
    关注

    Confusingly the Generate interface needs a function using the type not a the pointer to the type. You want your type signature to look like

    func (m Metadata) Generate(r *rand.Rand, size int) (value reflect.Value)

    You can play with this here. Note: the most important thing to do in that playground is to switch the type of the generate function from m Metadata to m *Metadata and see that Hi Mom! never prints.

    In addition, I think you would be better served using your own type and writing a generate method for that type using a list of all of the characters you want to use. For example:

    type LatinString string
    const latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01233456789"
    

    and then use the generator

    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)
    }
    

    playground

    Edit: also this library is pretty cool, thanks for showing it to me

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?