Преобразование интерфейсных переменных в Голанге - PullRequest
0 голосов
/ 16 октября 2018

У меня есть переменная, значение которой может быть строковым или int зависит от ввода.Я использую interface{} в качестве типа.Как преобразовать значение этой переменной в int, если ввод имеет вид "50", "45" или любая строка типа 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?

Ответы [ 3 ]

0 голосов
/ 16 октября 2018

пакет 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

0 голосов
/ 16 октября 2018

Как я понял ваш вопрос, значение вашего 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

0 голосов
/ 16 октября 2018

В Go, в отличие от таких языков, как Python / JavaScript / Perl, переменные имеют строгие типы и строгие границы.Вы должны написать явный код, чтобы сделать преобразование строки из / в целое число.Это полезно для написания более безопасных и более производительных программ.

Кроме того, если переменная хранится в interface{}, необходимо использовать утверждение типа (или переключатель типа) для дальнейшего использования содержимого сопределенный тип.

Вот ваш фиксированный код :

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 для предельной переменной.

...