blue panther
blue panther

Reputation: 253

Interface variable conversion in Golang

I have a variable which value can be string or int depend on the input. I use interface{} as the type. How to convert the value of that variable to int if the input is like "50", "45", or any string of 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)
}

Above code got:

interface conversion: interface {} is string, not int

If I use this:

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)
}

I got this

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

How to convert value of that variable to int?

Upvotes: 1

Views: 5922

Answers (3)

dolmen
dolmen

Reputation: 8706

In Go, in contrast to languages such as Python/JavaScript/Perl, the variables have strict types and strong boundaries. You have to write explicit code to make the conversion of a string from/to an integer. This is helpful to write safer and more performant programs.

In addition, if the variable is stored in an interface{} you have to use a type assertion (or a type switch) to further use the content with a specific type.

Here is your 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)
}

However, I suggest that you just use the string type for the limit variable.

Upvotes: 1

Alex Medveshchek
Alex Medveshchek

Reputation: 685

As I understood your question, value of your limit in fact is always string, but in one case it's value == ALL, otherwise it's a string representation of an integer value.

If I'm right, then I would provide following solution:

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
}

Full solution on playground: https://play.golang.org/p/fJv9_cw18R5

Upvotes: 0

ASHWIN RAJEEV
ASHWIN RAJEEV

Reputation: 2891

strconv package can use for this kind of conversion

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)
}

Output of the above code:

Type is: string, Value is: 10 After conversion value is: 10

Upvotes: 0

Related Questions