【问题标题】:Interface variable conversion in GolangGolang 中的接口变量转换
【发布时间】:2018-10-16 06:03:36
【问题描述】:

我有一个变量,它的值可以是字符串或整数,取决于输入。我使用interface{} 作为类型。如果输入类似于 "50""45" 或任何 int 字符串,如何将该变量的值转换为 int

package main

import "fmt"
import "log"
import "strconv"

func main() {
  var limit interface{}
  limit = "50"
  page := 1
  offset := 0
  if limit != "ALL" {
        log.Println("INSIDE")
        offset = limit.(int)*page - limit.(int)
    }
    fmt.Println(offset)
}

以上代码得到:

interface conversion: interface {} is string, not int

如果我使用这个:

package main

import "fmt"
import "log"
import "strconv"

func main() {
  var limit interface{}
  limit = "50"
  page := 1
  offset := 0
  if limit != "ALL" {
        log.Println("INSIDE")
        offset = strconv.Atoi(limit)*page - strconv.Atoi(limit)
    }
  fmt.Println(offset)
}

我知道了

exit status 2
 command-line-arguments
./main.go:14:24: cannot use limit (type interface {}) as type string in argument to strconv.Atoi: need type assertion
./main.go:14:24: multiple-value strconv.Atoi() in single-value context
./main.go:14:51: cannot use limit (type interface {}) as type string in argument to strconv.Atoi: need type assertion
./main.go:14:51: multiple-value strconv.Atoi() in single-value context

如何将该变量的值转换为 int?

【问题讨论】:

  • 投反对票,需要解释一下吗?
  • 你只是不能。这不是 Go 的工作方式。请参加围棋之旅。在此处停止使用 interface{}。您的限制是示例中的字符串,因此请使用 Atoi 进行转换。您必须获得正确的类型,这是通过了解 Go 的类型系统来完成的。现在学习。请阅读并理解错误消息:它们准确地描述了您做错了什么。

标签: go type-conversion


【解决方案1】:

在 Go 中,与 Python/JavaScript/Perl 等语言相比,变量具有严格的类型和强大的边界。您必须编写显式代码才能将字符串从/转换为整数。这有助于编写更安全、性能更高的程序。

此外,如果变量存储在interface{} 中,您必须使用类型断言(或类型切换)来进一步使用具有特定类型的内容。

这是你的fixed code

package main

import "fmt"
import "log"
import "strconv"

func main() {
    var limit interface{}
    limit = "50"
    page := 1
    offset := 3
    if limit != "ALL" {
        // Type assertion
        s, isString := limit.(string)
        if !isString {
            log.Fatalf("limit is not a string but %T", limit)
        }
        // Conversion from string to int, with error handling
        l, err := strconv.Atoi(s)
        if err != nil {
            log.Fatalf("%s: %v", limit, err)
        }
        offset = l*page - l
    }
    fmt.Println(offset)
}

但是,我建议您只使用string 类型作为限制变量。

【讨论】:

    【解决方案2】:

    strconv 包可以用于这种转换

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    func main() {
        var lim interface{}
        lim = "10"
        fmt.Printf("Type is: %T\nValue is: %s \n", lim, lim.(string))
        i, _ := strconv.Atoi(lim.(string))
        fmt.Printf("After conversion value is: %d", i)
    }
    

    以上代码的输出:

    类型是:字符串,值是:10 转化后的值为:10

    【讨论】:

    【解决方案3】:

    据我了解,您的limit 的值实际上始终是字符串,但在一种情况下它的值 == ALL,否则它是整数值的字符串表示形式。

    如果我是对的,那么我将提供以下解决方案:

    import (
        "errors"
        "fmt"
        "strconv"
    )
    
    func getOffset(limit string, page int64) (int64, error) {
        lim, err := strconv.ParseInt(limit, 10, 64)
        if err != nil {
            if limit == "ALL" {
                return 0, nil
            }
    
            return 0, errors.New(fmt.Sprintf("string '%v' doesn't fit requirements, error: %v", limit, err))
        }
    
        offset := lim*page - lim
        return offset, nil
    }
    

    操场上的完整解决方案:https://play.golang.org/p/fJv9_cw18R5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-20
      • 2015-07-21
      • 1970-01-01
      • 2014-10-24
      • 2022-01-18
      • 2014-01-13
      • 2015-05-16
      • 2021-12-06
      相关资源
      最近更新 更多