Golang中Unicode "Is"函数 - 哪个最值得使用?

Golang中Unicode "Is"函数 - 哪个最值得使用? 我明白这可能有些主观,所以我会尽量概述我比较确定的部分,以尽可能缩小关注范围。

我想进行一些基本的登录名检查。我的目标是允许所有可能在姓名中使用的Unicode字符,包括非英语语言中的字符,以及数字和可能在姓名中出现的基本标点符号,但不包括像 !, ? 这样的书写标点符号,也不包括像CR、LF等控制字符,不过在这种情况下允许使用空格。

显然应该允许的是:unicode.IsDigit/unicode.IsNumberunicode.IsLetter,并且不使用 IsControl。但我对 IsMark 不太清楚,因为它看起来有些子类别可能有用,有些则不然。另外,我对 IsGraphic 没有概念,对 IsPunct 也不确定。

有没有人深入研究过Unicode,对于允许哪些Unicode字符是合理的选择有什么想法吗?

更新: 在尝试了来自不同国家的词语后,我目前得出了以下方案:

  switch  {
  case unicode.IsDigit(chr), unicode.IsLetter(chr), unicode.IsSpace(chr), unicode.Is(unicode.Dash, chr), unicode.Is(unicode.Hyphen, chr):
  case unicode.IsPunct(chr):
    if !strings.ContainsAny(string(chr),"’'ʼ՚ߴߵߵ’'") { // 撇号
      logger.Error(`Message`)
    }
  default :
    logger.Error(`Message`)
  }

更多关于Golang中Unicode "Is"函数 - 哪个最值得使用?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中Unicode "Is"函数 - 哪个最值得使用?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go的unicode包中,IsGraphicIsPrint函数对于登录名验证可能是最合适的选择。IsGraphic涵盖了所有图形字符(字母、数字、标点、符号、空白),而IsPrint在此基础上排除了控制字符。对于你的用例,我建议使用IsGraphic并排除特定标点。

以下是更清晰的实现示例:

func isValidLoginNameChar(chr rune) bool {
    // 首先检查基本允许的类别
    if unicode.IsDigit(chr) || unicode.IsLetter(chr) || unicode.IsSpace(chr) {
        return true
    }
    
    // 允许特定标点
    if chr == '-' || chr == '_' || chr == '.' || chr == '\'' {
        return true
    }
    
    // 使用IsGraphic检查其他图形字符,但排除不需要的标点
    if unicode.IsGraphic(chr) {
        // 排除特定标点符号
        switch chr {
        case '!', '?', '@', '#', '$', '%', '^', '&', '*', '(', ')', 
             '=', '+', '[', ']', '{', '}', '|', '\\', ';', ':', '"', 
             '<', '>', '/', '~', '`':
            return false
        default:
            // 检查是否为控制字符(虽然IsGraphic通常已排除)
            if unicode.IsControl(chr) {
                return false
            }
            return true
        }
    }
    
    return false
}

// 完整验证函数
func ValidateLoginName(name string) bool {
    for _, chr := range name {
        if !isValidLoginNameChar(chr) {
            return false
        }
    }
    return true
}

或者使用更简洁的IsPrint方案:

func isValidLoginNameChar(chr rune) bool {
    // 允许的标点白名单
    allowedPunct := map[rune]bool{
        '-': true, '_': true, '.': true, '\'': true,
        'ʼ': true, '՚': true, '’': true, ''': true,
    }
    
    // 排除的标点黑名单
    excludedPunct := map[rune]bool{
        '!': true, '?': true, '@': true, '#': true,
        '$': true, '%': true, '^': true, '&': true,
        '*': true, '(': true, ')': true, '=': true,
        '+': true, '[': true, ']': true, '{': true,
        '}': true, '|': true, '\\': true, ';': true,
        ':': true, '"': true, '<': true, '>': true,
        '/': true, '~': true, '`': true,
    }
    
    // 基本检查
    if unicode.IsDigit(chr) || unicode.IsLetter(chr) || unicode.IsSpace(chr) {
        return true
    }
    
    // 检查标点
    if unicode.IsPunct(chr) {
        if excludedPunct[chr] {
            return false
        }
        return allowedPunct[chr]
    }
    
    // 其他可打印字符
    return unicode.IsPrint(chr) && !unicode.IsControl(chr)
}

对于IsMark,通常不需要包含,因为它主要处理变音符号(如重音符号),这些已经包含在IsLetter的某些实现中。IsGraphicIsPrint能更好地处理国际字符的显示需求。

回到顶部