How to compare two version number strings in golang

前端 未结 10 663
别跟我提以往
别跟我提以往 2020-12-30 02:06

I have two strings (they are actually version numbers and they could be any version numbers)

a := \"1.05.00.0156\"  
b := \"1.0.221.9289\"

相关标签:
10条回答
  • 2020-12-30 02:19

    Striving for clarity and simplicity:

    func intVer(v string) (int64, error) {
        sections := strings.Split(v, ".")
        intVerSection := func(v string, n int) string {
            if n < len(sections) {
                return fmt.Sprintf("%04s", sections[n])
            } else {
                return "0000"
            }
        }
        s := ""
        for i := 0; i < 4; i++ {
            s += intVerSection(v, i)
        }
        return strconv.ParseInt(s, 10, 64)
    }
    
    func main() {
        a := "3.045.98.0832"
        b := "087.2345"
        va, _ := intVer(a)
        vb, _ := intVer(b)
        fmt.Println(va<vb)
    }
    

    Comparing versions implies parsing so I believe these 2 steps should be separate to make it robust.

    0 讨论(0)
  • 2020-12-30 02:23

    Convert "1.05.00.0156" to "0001"+"0005"+"0000"+"0156", then to int64.

    Convert "1.0.221.9289" to "0001"+"0000"+"0221"+"9289", then to int64.

    Compare the two int64 values.

    Try it on the Go playground

    0 讨论(0)
  • 2020-12-30 02:23
    import (
        "fmt"
        "strconv"
        "strings"
    )
    
    
    func main() {
        j := ll("1.05.00.0156"  ,"1.0.221.9289")
       fmt.Println(j)
    }
    
    
    func ll(a,b string) int {
        var length ,r,l int = 0,0,0
        v1 := strings.Split(a,".")
        v2 := strings.Split(b,".")
        len1, len2 := len(v1), len(v2)
    
        length = len2
        if len1 > len2 {
           length = len1
        }
    
        for i:= 0;i<length;i++ {
            if i < len1 && i < len2 {
                if v1[i] == v2[i] {
                    continue
                }
            }
            r = 0
            if i < len1 {
                if number, err := strconv.Atoi(v1[i]); err == nil {
                    r = number
                }
            }
    
            l = 0
            if i < len2 {
                if number, err := strconv.Atoi(v2[i]); err == nil {
                    l = number
                }
            }
    
            if r < l {
                return -1
            }else if r> l {
                return 1
            }
        }
    
        return 0
    }
    
    0 讨论(0)
  • 2020-12-30 02:23

    Here are some of the libraries for version comparison:

    1. https://github.com/blang/semver
    2. https://github.com/Masterminds/semver
    3. https://github.com/hashicorp/go-version
    4. https://github.com/mcuadros/go-version

    I have used blang/semver. Eg: https://play.golang.org/p/1zZvEjLSOAr

     import github.com/blang/semver/v4
     
      v1, err := semver.Make("1.0.0-beta")
      v2, err := semver.Make("2.0.0-beta")
     
      // Options availabe
      v1.Compare(v2)  // Compare
      v1.LT(v2)       // LessThan
      v1.GT(v2)       // GreaterThan

    0 讨论(0)
  • 2020-12-30 02:24

    go-semver is a semantic versioning library for Go. It lets you parse and compare two semantic version strings.

    Example:

    vA := semver.New("1.2.3")
    vB := semver.New("3.2.1")
    
    fmt.Printf("%s < %s == %t\n", vA, vB, vA.LessThan(*vB))
    

    Output:

    1.2.3 < 3.2.1 == true

    0 讨论(0)
  • 2020-12-30 02:25

    Here's a general solution.

    package main
    
    import "fmt"
    
    func VersionOrdinal(version string) string {
        // ISO/IEC 14651:2011
        const maxByte = 1<<8 - 1
        vo := make([]byte, 0, len(version)+8)
        j := -1
        for i := 0; i < len(version); i++ {
            b := version[i]
            if '0' > b || b > '9' {
                vo = append(vo, b)
                j = -1
                continue
            }
            if j == -1 {
                vo = append(vo, 0x00)
                j = len(vo) - 1
            }
            if vo[j] == 1 && vo[j+1] == '0' {
                vo[j+1] = b
                continue
            }
            if vo[j]+1 > maxByte {
                panic("VersionOrdinal: invalid version")
            }
            vo = append(vo, b)
            vo[j]++
        }
        return string(vo)
    }
    
    func main() {
        versions := []struct{ a, b string }{
            {"1.05.00.0156", "1.0.221.9289"},
            // Go versions
            {"1", "1.0.1"},
            {"1.0.1", "1.0.2"},
            {"1.0.2", "1.0.3"},
            {"1.0.3", "1.1"},
            {"1.1", "1.1.1"},
            {"1.1.1", "1.1.2"},
            {"1.1.2", "1.2"},
        }
        for _, version := range versions {
            a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
            switch {
            case a > b:
                fmt.Println(version.a, ">", version.b)
            case a < b:
                fmt.Println(version.a, "<", version.b)
            case a == b:
                fmt.Println(version.a, "=", version.b)
            }
        }
    }
    

    Output:

    1.05.00.0156 > 1.0.221.9289
    1 < 1.0.1
    1.0.1 < 1.0.2
    1.0.2 < 1.0.3
    1.0.3 < 1.1
    1.1 < 1.1.1
    1.1.1 < 1.1.2
    1.1.2 < 1.2
    
    0 讨论(0)
提交回复
热议问题