【转】 http://www.syyong.com/Go/Go-implementation-version-comparison-VersionCompare-function.html

VersionCompare — 用于对比两个的版本数字字符串大小。

此函数首先在版本字符串里用一个点 . 替换 _、- 和 +,也会在任意非数字前后插入一个点 .,这样,类似 '4.3.2RC1' 将会变成 '4.3.2.RC.1'。 接下来它会分割结果,然后它会从左往右对比各个部分。如果某部分包含了特定的版本字符串,将会用以下顺序处理:列表中未找到的任意字符串 < dev < alpha = a < beta = b < RC = rc < # < pl = p。 这种方式不仅能够对比类似 '4.1' 和 '4.1.2' 那种不同的版本级别,同时也可以指定对比任何包含开发状态的版本。

VersionCompare

// version_compare()
// The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
// special version strings these are handled in the following order,
// (any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
// Usage:
// VersionCompare("1.2.3-alpha", "1.2.3RC7", '>=')
// VersionCompare("1.2.3-beta", "1.2.3pl", 'lt')
// VersionCompare("1.1_dev", "1.2any", 'eq')
func VersionCompare(version1, version2, operator string) bool {
var vcompare func(string, string) int
var canonicalize func(string) string
var special func(string, string) int // version compare
vcompare = func(origV1, origV2 string) int {
if origV1 == "" || origV2 == "" {
if origV1 == "" && origV2 == "" {
return
} else {
if origV1 == "" {
return -
} else {
return
}
}
} ver1, ver2, compare := "", "",
if origV1[] == '#' {
ver1 = origV1
} else {
ver1 = canonicalize(origV1)
}
if origV2[] == '#' {
ver2 = origV2
} else {
ver2 = canonicalize(origV2)
}
n1, n2 := ,
for {
p1, p2 := "", ""
n1 = strings.IndexByte(ver1, '.')
if n1 == - {
p1, ver1 = ver1, ""
} else {
p1, ver1 = ver1[:n1], ver1[n1+:]
}
n2 = strings.IndexByte(ver2, '.')
if n2 == - {
p2, ver2 = ver2, ""
} else {
p2, ver2 = ver2[:n2], ver2[n2+:]
}
if (p1[] >= '' && p1[] <= '') && (p2[] >= '' && p2[] <= '') { // all isdigit
l1, _ := strconv.Atoi(p1)
l2, _ := strconv.Atoi(p2)
if l1 > l2 {
compare =
} else if l1 == l2 {
compare =
} else {
compare = -
}
} else if !(p1[] >= '' && p1[] <= '') && !(p2[] >= '' && p2[] <= '') { // all isndigit
compare = special(p1, p2)
} else { // part isdigit
if p1[] >= '' && p1[] <= '' { // isdigit
compare = special("#N#", p2)
} else {
compare = special(p1, "#N#")
}
}
if compare != || n1 == - || n2 == - {
break
}
} if compare == {
if ver1 != "" {
if ver1[] >= '' && ver1[] <= '' {
compare =
} else {
compare = vcompare(ver1, "#N#")
}
} else if ver2 != "" {
if ver2[] >= '' && ver2[] <= '' {
compare = -
} else {
compare = vcompare("#N#", ver2)
}
}
} return compare
} // canonicalize
canonicalize = func(version string) string {
ver := []byte(version)
l := len(ver)
if l == {
return ""
}
var buf = make([]byte, l*)
j :=
for i, v := range ver {
next := uint8()
if i+ < l { // Have the next one
next = ver[i+]
}
if v == '-' || v == '_' || v == '+' { // repalce "-","_","+" to "."
if j > && buf[j-] != '.' {
buf[j] = '.'
j++
}
} else if (next > ) &&
(!(next >= '' && next <= '') && (v >= '' && v <= '')) ||
(!(v >= '' && v <= '') && (next >= '' && next <= '')) { // Insert '.' before and after a non-digit
buf[j] = v
j++
if v != '.' && next != '.' {
buf[j] = '.'
j++
}
continue
} else if !((v >= '' && v <= '') ||
(v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')) { // Non-letters and numbers
if j > && buf[j-] != '.' {
buf[j] = '.'
j++
}
} else {
buf[j] = v
j++
}
} return string(buf[:j])
} //compare special version forms
special = func(form1, form2 string) int {
found1, found2, len1, len2 := -, -, len(form1), len(form2)
// (Any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
forms := map[string]int{
"dev": ,
"alpha": ,
"a": ,
"beta": ,
"b": ,
"RC": ,
"rc": ,
"#": ,
"pl": ,
"p": ,
} for name, order := range forms {
if len1 < len(name) {
continue
}
if strings.Compare(form1[:len(name)], name) == {
found1 = order
break
}
}
for name, order := range forms {
if len2 < len(name) {
continue
}
if strings.Compare(form2[:len(name)], name) == {
found2 = order
break
}
} if found1 == found2 {
return
} else if found1 > found2 {
return
} else {
return -
}
} compare := vcompare(version1, version2) switch operator {
case "<", "lt":
return compare == -
case "<=", "le":
return compare !=
case ">", "gt":
return compare ==
case ">=", "ge":
return compare != -
case "==", "=", "eq":
return compare ==
case "!=", "<>", "ne":
return compare !=
default:
panic("operator: invalid")
}
}

Github地址

https://github.com/syyongx/php2go

Go 完整实现版本比较 VersionCompare 函数的更多相关文章

  1. Delphi 版本信息获取函数 GetFileVersionInfo、GetFileVersionInfoSize、VerFindFile、VerInstallFile和VerQueryValue

    一.版本信息获取函数简介和作用 获取文件版本信息的作用: 1. 避免在新版本的组件上安装旧版本的相同组件: 2. 在多语言系统环境中,操作系统根据文件版本信息里提供的语言信息在启动程序时决定使用的正确 ...

  2. Axis2联接WCF(比较完整的版本)

    Axis2联接WCF(比较完整的版本) 分basicHttpBinding和wsHttpBinding两种情况: 一.basicHttpBinding比较简单一点,先来看看它所要求的HTTP包:POS ...

  3. PHP 版本判断 version_compare() 函数

    在度娘中简单的找了下,判断当前PHP的版本是否高于某个版本,或者低于某个版本的方法 显示的结果基本上都是一样的,好吧,要不是我忘记了version_compare()这个函数我才不会去找度娘,果断找以 ...

  4. iOS开发之单例设计模式(完整正确版本)

    单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例.可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类.工具类以及其它管理类等.比如我iOS开发中 ...

  5. Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数

    条款17 在operator=中检查给自己赋值的情况 1 2 3 class  X { ... }; X a; a = a;  // a 赋值给自己 >赋值给自己make no sense, 但 ...

  6. 一个完整的DLL远程注入函数

    函数名称: CreateRemoteDll() 返加类型:BOOL 接受参数: DLL路径,注入进程ID 其完整代码如下: BOOL CreateRemoteDll(const char *DllFu ...

  7. creator 2.0版本对于preloadScene函数获取加载进度

    有时候,当我们场景上挂载的资源过多时,我们使用cc.director.loadScene切换场景时会等一段时间才会切换过去,这对游戏的体验是相当不好的.所以我们可以使用cc.director.prel ...

  8. 获取Exe文件版本信息的函数(使用GetFileVersionInfo得到TFileVersionInfo结构体,包含12项内容)

    Type   TFileVersionInfo   =   Record         FixedInfo:TVSFixedFileInfo;         {版本信息}         Comp ...

  9. jQuery总结--版本二 事件处理函数

    一:事件处理函数 (1) one(事件名称, fn) 仅对指定事件监听一次,监听事件只会执行一次 <!DOCTYPE html> <html> <head lang=&q ...

随机推荐

  1. Web Api 接收图片

    public async Task<HttpResponseMessage> Upload() { if (!Request.Content.IsMimeMultipartContent( ...

  2. python3 常用模块

    一.time与datetime模块 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们 ...

  3. mangodb的基本操作:增删改差

    MongoDB三元素: 1 数据库: 和关系型数据库中数据库的层次相同,内部可以有多个集合. 2 集合: 相当于关系型数据库中的表,存储若干文档,结构不固定 3 文档: 相当于关系型数据库中的行,是J ...

  4. python/*args和**kwargs

    *args和**kwargs #coding=utf8 __author__ = 'Administrator' # 当函数的参数不确定时,可以使用*args和**kwargs.*args没有key值 ...

  5. python/数据库操作补充—模板—Session

    python/数据库操作补充—模板—Session 一.创建一个app目录 在models.py只能类进行进行创建表 class Foo: xx= 字段(数据库数据类型) 字段类型 字符串 Email ...

  6. [转]pycharm常用快捷键及设置

    PyCharm3.0默认快捷键(翻译的) PyCharm Default Keymap 1.编辑(Editing) Ctrl + Space    基本的代码完成(类.方法.属性)Ctrl + Alt ...

  7. js中的栈与堆的讲解/基本数据类型与引用类型的讲解

    1.栈(stack)和堆(heap) stack为自动分配的内存空间,它由系统自动释放:而heap则是动态分配的内存,大小不定也不会自动释放. 2.基本类型和引用类型 基本类型:存放在栈内存中的简单数 ...

  8. JavaScript的数组实现队列与堆栈的方法

    一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被取出! 如下图所示: 1.2.堆栈的基本概念 堆栈:是一种支持后进先出(LIFO)的 ...

  9. 基于 MySQL 的数据库实践(基本查询)

    首先根据准备工作中的操作导入大学模式,打开数据库连接后进入到 MySQL 的交互界面,再使用命令 use db-book; 切换到 db-book 数据库. 单关系查询 SQL 查询的基本结构由三个子 ...

  10. vue-cli 体验

    vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一. ...