FAQ
I am performing a type assertion (as my passed in type is
map[string]interface{}. When I assign the value to a variable as such:

(*D).Memory = m["memory"].(int32)

I get the following panic:

panic: interface conversion: interface is int, not int32

goroutine 1 [running]:
runtime.panic(0x4a3c20, 0xc210047000)
/usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
test/device.(*Device).Init(0xc210046000, 0xc21001e390)
/home/user/Development/Go/src/test/device/device.go:112 +0x5fa
main.main()
/home/user/Development/Go/src/test/main.go:12 +0x201
exit status 2

If I change the value from int32 to int64 I get the same, but when I change
the values to int along it all works fine. Given, I have to change the
corresponding struct to int64's and int's as well, that is done.


I have been told this is not a bug, understanding why it isn't, would be
nice. Thanks

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Paul Borman at Jun 1, 2015 at 2:54 pm
    What is m? I assume a map[string]interface{}? In that case you can
    convert the interface into something other than its concrete type. So:

    t := m["memory].(int)
    (*D).Memory = int32(t)

         -Paul
    On Mon, Jun 1, 2015 at 7:25 AM, wrote:

    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    goroutine 1 [running]:
    runtime.panic(0x4a3c20, 0xc210047000)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
    test/device.(*Device).Init(0xc210046000, 0xc21001e390)
    /home/user/Development/Go/src/test/device/device.go:112 +0x5fa
    main.main()
    /home/user/Development/Go/src/test/main.go:12 +0x201
    exit status 2

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would be
    nice. Thanks

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 1, 2015 at 3:17 pm
    so m is what gets passed in and looks roughly like:

    map[string]interface{}{"name":"rikers01","cpu":2,"memory":4096}

    the workaround you have works, I am more trying to understand why a type
    assert to int32 or int64 is such a problem. I am trying to keep my code
    compact and simple, so I want to reduce the clutter as it were. Plus every
    conversion comes at a small cost and they pile up. Thanks

    Tim
    On Mon, Jun 1, 2015 at 10:53 AM, Paul Borman wrote:

    What is m? I assume a map[string]interface{}? In that case you can
    convert the interface into something other than its concrete type. So:

    t := m["memory].(int)
    (*D).Memory = int32(t)

    -Paul
    On Mon, Jun 1, 2015 at 7:25 AM, wrote:

    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    goroutine 1 [running]:
    runtime.panic(0x4a3c20, 0xc210047000)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
    test/device.(*Device).Init(0xc210046000, 0xc21001e390)
    /home/user/Development/Go/src/test/device/device.go:112 +0x5fa
    main.main()
    /home/user/Development/Go/src/test/main.go:12 +0x201
    exit status 2

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would be
    nice. Thanks

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Brad Fitzpatrick at Jun 1, 2015 at 3:22 pm
    You should really strive to avoid map[string]interface{} in the first place
    and use a proper type for your data.

    On Mon, Jun 1, 2015 at 8:16 AM, Tim Epkes wrote:

    so m is what gets passed in and looks roughly like:

    map[string]interface{}{"name":"rikers01","cpu":2,"memory":4096}

    the workaround you have works, I am more trying to understand why a type
    assert to int32 or int64 is such a problem. I am trying to keep my code
    compact and simple, so I want to reduce the clutter as it were. Plus every
    conversion comes at a small cost and they pile up. Thanks

    Tim
    On Mon, Jun 1, 2015 at 10:53 AM, Paul Borman wrote:

    What is m? I assume a map[string]interface{}? In that case you can
    convert the interface into something other than its concrete type. So:

    t := m["memory].(int)
    (*D).Memory = int32(t)

    -Paul
    On Mon, Jun 1, 2015 at 7:25 AM, wrote:

    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    goroutine 1 [running]:
    runtime.panic(0x4a3c20, 0xc210047000)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
    test/device.(*Device).Init(0xc210046000, 0xc21001e390)
    /home/user/Development/Go/src/test/device/device.go:112 +0x5fa
    main.main()
    /home/user/Development/Go/src/test/main.go:12 +0x201
    exit status 2

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would be
    nice. Thanks

    --
    You received this message because you are subscribed to the Google
    Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send
    an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 1, 2015 at 3:27 pm
    I am a python programmer traditionally and use defaults that have a
    dictionaries with different values in each field. It is a very nice way to
    get defaults into a class. I am trying to emulate that functionality in
    Go. I find being constrained to a certain type constantly problematic.
    The interface{} seemed like the right fit and from what I read is one of
    the things it does. I also want to see if I get the flexibility of Python
    in Go. So far it has been very accommodating, this particular aspect was
    a must have for me. Are you saying it is not correct to use it?

    Thanks in advance
    On Mon, Jun 1, 2015 at 11:21 AM, Brad Fitzpatrick wrote:

    You should really strive to avoid map[string]interface{} in the first
    place and use a proper type for your data.

    On Mon, Jun 1, 2015 at 8:16 AM, Tim Epkes wrote:

    so m is what gets passed in and looks roughly like:

    map[string]interface{}{"name":"rikers01","cpu":2,"memory":4096}

    the workaround you have works, I am more trying to understand why a type
    assert to int32 or int64 is such a problem. I am trying to keep my code
    compact and simple, so I want to reduce the clutter as it were. Plus every
    conversion comes at a small cost and they pile up. Thanks

    Tim
    On Mon, Jun 1, 2015 at 10:53 AM, Paul Borman wrote:

    What is m? I assume a map[string]interface{}? In that case you can
    convert the interface into something other than its concrete type. So:

    t := m["memory].(int)
    (*D).Memory = int32(t)

    -Paul
    On Mon, Jun 1, 2015 at 7:25 AM, wrote:

    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    goroutine 1 [running]:
    runtime.panic(0x4a3c20, 0xc210047000)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
    test/device.(*Device).Init(0xc210046000, 0xc21001e390)
    /home/user/Development/Go/src/test/device/device.go:112 +0x5fa
    main.main()
    /home/user/Development/Go/src/test/main.go:12 +0x201
    exit status 2

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would
    be nice. Thanks

    --
    You received this message because you are subscribed to the Google
    Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send
    an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Volker Dobler at Jun 1, 2015 at 3:26 pm

    Am Montag, 1. Juni 2015 16:50:51 UTC+2 schrieb tim....@gmail.com:
    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would be
    nice. Thanks
    int, int32, int63 are all different types and have nothing in common but
    the name (well, almost). You cannot type assert one into the other.

    V.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 1, 2015 at 3:32 pm
    I am actually not type asserting one for another. My struct variable
    Memory is an int32 and I am trying to type assert into int32. So int32 to
    int32. But due to this issue, I have to either change my struct to int and
    then assert into int or I can keep my struct variable int32, type assert as
    int and then cast as int32.

    All I want to understand is why I can't type assert as int32 or int64?

    Tim
    On Mon, Jun 1, 2015 at 11:26 AM, Volker Dobler wrote:

    Am Montag, 1. Juni 2015 16:50:51 UTC+2 schrieb tim....@gmail.com:
    I am performing a type assertion (as my passed in type is
    map[string]interface{}. When I assign the value to a variable as such:

    (*D).Memory = m["memory"].(int32)

    I get the following panic:

    panic: interface conversion: interface is int, not int32

    If I change the value from int32 to int64 I get the same, but when I
    change the values to int along it all works fine. Given, I have to change
    the corresponding struct to int64's and int's as well, that is done.


    I have been told this is not a bug, understanding why it isn't, would be
    nice. Thanks
    int, int32, int63 are all different types and have nothing in common but
    the name (well, almost). You cannot type assert one into the other.

    V.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 1, 2015 at 3:42 pm

    On Mon, Jun 1, 2015 at 8:31 AM, Tim Epkes wrote:
    I am actually not type asserting one for another. My struct variable Memory
    is an int32 and I am trying to type assert into int32. So int32 to int32.
    But due to this issue, I have to either change my struct to int and then
    assert into int or I can keep my struct variable int32, type assert as int
    and then cast as int32.

    All I want to understand is why I can't type assert as int32 or int64?
    You can.

    Show us a complete standalone example demonstrating the problem you
    are encountering.

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Andy Balholm at Jun 1, 2015 at 4:13 pm
    There are two operations in Go that “change” a value from one type to another, and beginners often get them confused.

    A type assertion—x.(type)—unwraps a value from an interface. The type specified must match the value’s type exactly, or it will fail. int32 and int are not exact matches, so your example fails. (Type assertions never change a value’s concrete type.)

    A conversion—type(x)—actually converts a value from one type to another. It is normally used with concrete types, not interfaces.

    The need to do both a type assertion and a conversion in your case is a result of Go’s policy of requiring explicit type conversions. C has a lot of implicit type conversion rules, and they are the source of confusing bugs.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 1, 2015 at 4:36 pm
    So basically the number I am passing

    map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,
    *"memory":4096*}

    in this case the memory, is equating to an int in the interfade? So when I
    try to assert a int32 it fails?

    is it that the number false in the range of an int on interface or is it
    that int is all interface supports? Both would make sense.

    Thanks in advance.

    Tim
    On Mon, Jun 1, 2015 at 12:12 PM, Andy Balholm wrote:

    There are two operations in Go that “change” a value from one type to
    another, and beginners often get them confused.

    A type assertion—x.(type)—unwraps a value from an interface. The type
    specified must match the value’s type exactly, or it will fail. int32 and
    int are not exact matches, so your example fails. (Type assertions never
    change a value’s concrete type.)

    A conversion—type(x)—actually converts a value from one type to another.
    It is normally used with concrete types, not interfaces.

    The need to do both a type assertion and a conversion in your case is a
    result of Go’s policy of requiring explicit type conversions. C has a lot
    of implicit type conversion rules, and they are the source of confusing
    bugs.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Paul Borman at Jun 1, 2015 at 4:39 pm
    memory *is* an int, the map stores an interface wrapping the int (basically
    a type field and a pointer to the real int)
    On Mon, Jun 1, 2015 at 9:35 AM, Tim Epkes wrote:

    So basically the number I am passing

    map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,
    *"memory":4096*}

    in this case the memory, is equating to an int in the interfade? So when I
    try to assert a int32 it fails?

    is it that the number false in the range of an int on interface or is it
    that int is all interface supports? Both would make sense.

    Thanks in advance.

    Tim
    On Mon, Jun 1, 2015 at 12:12 PM, Andy Balholm wrote:

    There are two operations in Go that “change” a value from one type to
    another, and beginners often get them confused.

    A type assertion—x.(type)—unwraps a value from an interface. The type
    specified must match the value’s type exactly, or it will fail. int32 and
    int are not exact matches, so your example fails. (Type assertions never
    change a value’s concrete type.)

    A conversion—type(x)—actually converts a value from one type to another.
    It is normally used with concrete types, not interfaces.

    The need to do both a type assertion and a conversion in your case is a
    result of Go’s policy of requiring explicit type conversions. C has a lot
    of implicit type conversion rules, and they are the source of confusing
    bugs.

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 1, 2015 at 5:09 pm

    On Mon, Jun 1, 2015 at 9:35 AM, Tim Epkes wrote:
    So basically the number I am passing

    map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096}

    in this case the memory, is equating to an int in the interfade? So when I
    try to assert a int32 it fails?

    is it that the number false in the range of an int on interface or is it
    that int is all interface supports? Both would make sense.
    You can store any type in an interface. But every value in an
    interface has a specific type, and you must use that exact type when
    writing a type assertion.

    Constants in Go are untyped. You are storing an untyped 4096 into an
    interface. In the absence of a type, the type selected for a integer
    number is "int". See the paragraph on default type in
    http://golang.org/ref/spec#Constants .

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 1, 2015 at 5:21 pm
    Thank you, that explains it. Awesome, thank you all for the help in better
    understanding the implementation.

    Tim
    On Mon, Jun 1, 2015 at 1:09 PM, Ian Lance Taylor wrote:
    On Mon, Jun 1, 2015 at 9:35 AM, Tim Epkes wrote:

    So basically the number I am passing

    map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096}
    in this case the memory, is equating to an int in the interfade? So when I
    try to assert a int32 it fails?

    is it that the number false in the range of an int on interface or is it
    that int is all interface supports? Both would make sense.
    You can store any type in an interface. But every value in an
    interface has a specific type, and you must use that exact type when
    writing a type assertion.

    Constants in Go are untyped. You are storing an untyped 4096 into an
    interface. In the absence of a type, the type selected for a integer
    number is "int". See the paragraph on default type in
    http://golang.org/ref/spec#Constants .

    Ian
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Brendan Tracey at Jun 2, 2015 at 6:29 am
    Now that your question is answered, I'll address the other point.

    While there exist exceptions, in general map[string]interface{} is not a
    good design decision. Usually, it would be better to do something like

    type Config struct {
         Name string
         Model string
         CPU int
         Memory int
    }

    If needed, you can then do

    func DefaultConfig() *Config {
         return &Config {
             Name: "GopherPlushie",
             Model: "Pink",
             CPU: 8,
             Memory: 1024,
         }
    }

    And in the user code
    config := pkg.DefaultConfig()
    config.CPU = 16


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 2, 2015 at 11:48 am
    Brendan,

    Thanks for the reply, definitely see that. Let me put an example of what I
    am doing. Sometimes I need a default based on model and the defaults are
    the pulled from that model. Example code:

    package main

    import (
             "strconv"
             )

    var defaults = map[string]map[string]string{
         "S93432": map[string]string{
             "vendor":"Sager",
             "memory":"16384",
             "cpu":"2"},
         "T40": map[string]string{
             "vendor":"Ibm",
             "memory":"2048",
             "cpu":"1"},
    }

    type Device struct{
         Name string
         Model string
         Vendor string
         Memory int32
         Cpu int
    }

    type Devices []Device

    func keyinlist(s string, m map[string]interface{}) bool {
         for k := range m {
             if k == s {
                 return true
             }
         }
         return false
    }

    func (D *Device) Init(m map[string]interface{}) {
             (*D).Name = m["name"].(string)
             (*D).Model = m["model"].(string)
             (*D).Vendor = defaults[m["model"].(string)]["vendor"]
             if keyinlist("memory",m) {
                 (*D).Memory = m["memory"].(int32)
             } else {
                 memory,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["memory"],10,32)
                 (*D).Memory = int32(memory)
             }
             if keyinlist("cpu",m) {
                 (*D).Cpu = m["cpu"].(int)
             } else {
                 cpu,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["cpu"],10,32)
                 (*D).Cpu = int(cpu)
             }
    }

    func main() {
         var d Devices
         mydev := new(Device)

    mydev.Init(map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096})
         d = append(d, *mydev)
    }


    This makes it very easy to initialize a device based on its model type. If
    a default configuration for a T40 laptop is 2G of mem and 2 CPU's, then it
    gets taken in at initialization. Now this code is stripped down and I have
    checks to make sure you pass in a model and a name. I can do this in
    Python very easily. This code now works as well, but I certainly don't
    want to not use best practices, so how would this be done otherwise?

    Thanks in advance

    Tim
    On Tue, Jun 2, 2015 at 2:29 AM, Brendan Tracey wrote:

    Now that your question is answered, I'll address the other point.

    While there exist exceptions, in general map[string]interface{} is not a
    good design decision. Usually, it would be better to do something like

    type Config struct {
    Name string
    Model string
    CPU int
    Memory int
    }

    If needed, you can then do

    func DefaultConfig() *Config {
    return &Config {
    Name: "GopherPlushie",
    Model: "Pink",
    CPU: 8,
    Memory: 1024,
    }
    }

    And in the user code
    config := pkg.DefaultConfig()
    config.CPU = 16

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Chris dollin at Jun 2, 2015 at 12:38 pm
    On 2 June 2015 at 12:48, Tim Epkes wrote:

    (Long quote follows before comments)
    package main

    import (
    "strconv"
    )

    var defaults = map[string]map[string]string{
    "S93432": map[string]string{
    "vendor":"Sager",
    "memory":"16384",
    "cpu":"2"},
    "T40": map[string]string{
    "vendor":"Ibm",
    "memory":"2048",
    "cpu":"1"},
    }

    type Device struct{
    Name string
    Model string
    Vendor string
    Memory int32
    Cpu int
    }

    type Devices []Device

    func keyinlist(s string, m map[string]interface{}) bool {
    for k := range m {
    if k == s {
    return true
    }
    }
    return false
    }

    func (D *Device) Init(m map[string]interface{}) {
    (*D).Name = m["name"].(string)
    (*D).Model = m["model"].(string)
    (*D).Vendor = defaults[m["model"].(string)]["vendor"]
    if keyinlist("memory",m) {
    (*D).Memory = m["memory"].(int32)
    } else {
    memory,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["memory"],10,32)
    (*D).Memory = int32(memory)
    }
    if keyinlist("cpu",m) {
    (*D).Cpu = m["cpu"].(int)
    } else {
    cpu,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["cpu"],10,32)
    (*D).Cpu = int(cpu)
    }
    }

    func main() {
    var d Devices
    mydev := new(Device)

    mydev.Init(map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096})
    d = append(d, *mydev)
    }


    This makes it very easy to initialize a device based on its model type. If
    a default configuration for a T40 laptop is 2G of mem and 2 CPU's, then it
    gets taken in at initialization. Now this code is stripped down and I have
    checks to make sure you pass in a model and a name. I can do this in Python
    very easily. This code now works as well, but I certainly don't want to not
    use best practices, so how would this be done otherwise?
    Does that not strike you as being horribly complicated for the job it
    seems to be doing? map[string]interface{} is very flexible but what you
    have above is basically using it as a struct where every field access
    needs a type assertion.

    Here's my version of your code.

    package main

    import (
         "fmt"
             )

    type Device struct{
         Name string
         Model string
         Vendor string
         Memory int32
         Cpu int
    }

    // the defaults are just default Device values, so we may as well
    // use the Device structs we already have.
    var defaults = map[string]Device{
         "S93432": Device{
             Vendor: "Sager",
             Memory: 16384,
             Cpu: 2},
         "T40": Device{
             Vendor: "Ibm",
             Memory: 2048,
             Cpu: 1},
    }

    // Instead of a method may we well use a function that is given
    // a possibly incomplete device and fills in the missing fields
    // from the defaults.
    func Init(d Device) Device {
         // if there's no default for the model then we'll get the
         // zero device value, which is OK. If it matters use the
         // two-result version of [] and complain if there's no value
         defaultDevice := defaults[d.Model]
         // check each defaultable value and copy from default
         if d.Cpu == 0 { d.Cpu = defaultDevice.Cpu }
         if d.Memory == 0 { d.Memory = defaultDevice.Memory }
         if d.Vendor == "" { d.Vendor = defaultDevice.Vendor }
         return d
    }

    func main() {
         // Make a (possibly partial) Device and fill it in from the defaults as per
         // Init
         d := []Device{Init(Device{Model: "T40", Name: "ultralight", Cpu:
    2, Memory: 4096})}
         fmt.Println(d)
    }

    No interface{}, no type assertions, no strconv, no keyinlist.

    Chris

    --
    Chris "allusive" Dollin

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 2, 2015 at 2:39 pm
    Thanks I'll give that a go. It seem complicated in Go, but in Python it
    makes things extremely easy. I see what you've done there, I'll try that
    and see if that works. That may be more efficient. I guess the question
    then is, if interface{} is a bad practice/not recommended, why is it there?

    Thanks in advance.

    Tim
    On Tue, Jun 2, 2015 at 8:38 AM, chris dollin wrote:

    On 2 June 2015 at 12:48, Tim Epkes wrote:

    (Long quote follows before comments)
    package main

    import (
    "strconv"
    )

    var defaults = map[string]map[string]string{
    "S93432": map[string]string{
    "vendor":"Sager",
    "memory":"16384",
    "cpu":"2"},
    "T40": map[string]string{
    "vendor":"Ibm",
    "memory":"2048",
    "cpu":"1"},
    }

    type Device struct{
    Name string
    Model string
    Vendor string
    Memory int32
    Cpu int
    }

    type Devices []Device

    func keyinlist(s string, m map[string]interface{}) bool {
    for k := range m {
    if k == s {
    return true
    }
    }
    return false
    }

    func (D *Device) Init(m map[string]interface{}) {
    (*D).Name = m["name"].(string)
    (*D).Model = m["model"].(string)
    (*D).Vendor = defaults[m["model"].(string)]["vendor"]
    if keyinlist("memory",m) {
    (*D).Memory = m["memory"].(int32)
    } else {
    memory,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["memory"],10,32)
    (*D).Memory = int32(memory)
    }
    if keyinlist("cpu",m) {
    (*D).Cpu = m["cpu"].(int)
    } else {
    cpu,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["cpu"],10,32)
    (*D).Cpu = int(cpu)
    }
    }

    func main() {
    var d Devices
    mydev := new(Device)

    mydev.Init(map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096})
    d = append(d, *mydev)
    }


    This makes it very easy to initialize a device based on its model type. If
    a default configuration for a T40 laptop is 2G of mem and 2 CPU's, then it
    gets taken in at initialization. Now this code is stripped down and I have
    checks to make sure you pass in a model and a name. I can do this in Python
    very easily. This code now works as well, but I certainly don't want to not
    use best practices, so how would this be done otherwise?
    Does that not strike you as being horribly complicated for the job it
    seems to be doing? map[string]interface{} is very flexible but what you
    have above is basically using it as a struct where every field access
    needs a type assertion.

    Here's my version of your code.

    package main

    import (
    "fmt"
    )

    type Device struct{
    Name string
    Model string
    Vendor string
    Memory int32
    Cpu int
    }

    // the defaults are just default Device values, so we may as well
    // use the Device structs we already have.
    var defaults = map[string]Device{
    "S93432": Device{
    Vendor: "Sager",
    Memory: 16384,
    Cpu: 2},
    "T40": Device{
    Vendor: "Ibm",
    Memory: 2048,
    Cpu: 1},
    }

    // Instead of a method may we well use a function that is given
    // a possibly incomplete device and fills in the missing fields
    // from the defaults.
    func Init(d Device) Device {
    // if there's no default for the model then we'll get the
    // zero device value, which is OK. If it matters use the
    // two-result version of [] and complain if there's no value
    defaultDevice := defaults[d.Model]
    // check each defaultable value and copy from default
    if d.Cpu == 0 { d.Cpu = defaultDevice.Cpu }
    if d.Memory == 0 { d.Memory = defaultDevice.Memory }
    if d.Vendor == "" { d.Vendor = defaultDevice.Vendor }
    return d
    }

    func main() {
    // Make a (possibly partial) Device and fill it in from the defaults
    as per
    // Init
    d := []Device{Init(Device{Model: "T40", Name: "ultralight", Cpu:
    2, Memory: 4096})}
    fmt.Println(d)
    }

    No interface{}, no type assertions, no strconv, no keyinlist.

    Chris

    --
    Chris "allusive" Dollin
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Brendan Tracey at Jun 2, 2015 at 2:46 pm
    There are some good uses of interface{}. A good example of it’s use is the fmt package. fmt can print arbitrary types, so interface{} is a good input parameter.

    It’s map[string]interface{} that is usually a bad idea. The config struct approach will be faster, but that’s not the main benefit. The real power is that the config struct is compile-time safe, so you’ll never put the wrong type there, and the definition of the struct also provides documentation of the parameters. Any string can go into the map, so if a user wants to find what they can control, they have to trust that the doc comment is correct or they have to scour the code for uses of the map. In a config struct, all the available options (and what type the option is) can be seen right there in the definition of the struct.

    On Jun 2, 2015, at 7:39 AM, Tim Epkes wrote:

    Thanks I'll give that a go. It seem complicated in Go, but in Python it makes things extremely easy. I see what you've done there, I'll try that and see if that works. That may be more efficient. I guess the question then is, if interface{} is a bad practice/not recommended, why is it there?

    Thanks in advance.

    Tim

    On Tue, Jun 2, 2015 at 8:38 AM, chris dollin wrote:
    On 2 June 2015 at 12:48, Tim Epkes wrote:

    (Long quote follows before comments)
    package main

    import (
    "strconv"
    )

    var defaults = map[string]map[string]string{
    "S93432": map[string]string{
    "vendor":"Sager",
    "memory":"16384",
    "cpu":"2"},
    "T40": map[string]string{
    "vendor":"Ibm",
    "memory":"2048",
    "cpu":"1"},
    }

    type Device struct{
    Name string
    Model string
    Vendor string
    Memory int32
    Cpu int
    }

    type Devices []Device

    func keyinlist(s string, m map[string]interface{}) bool {
    for k := range m {
    if k == s {
    return true
    }
    }
    return false
    }

    func (D *Device) Init(m map[string]interface{}) {
    (*D).Name = m["name"].(string)
    (*D).Model = m["model"].(string)
    (*D).Vendor = defaults[m["model"].(string)]["vendor"]
    if keyinlist("memory",m) {
    (*D).Memory = m["memory"].(int32)
    } else {
    memory,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["memory"],10,32)
    (*D).Memory = int32(memory)
    }
    if keyinlist("cpu",m) {
    (*D).Cpu = m["cpu"].(int)
    } else {
    cpu,_ :=
    strconv.ParseInt(defaults[m["model"].(string)]["cpu"],10,32)
    (*D).Cpu = int(cpu)
    }
    }

    func main() {
    var d Devices
    mydev := new(Device)

    mydev.Init(map[string]interface{}{"name":"ultralight","model":"T40","cpu":2,"memory":4096})
    d = append(d, *mydev)
    }


    This makes it very easy to initialize a device based on its model type. If
    a default configuration for a T40 laptop is 2G of mem and 2 CPU's, then it
    gets taken in at initialization. Now this code is stripped down and I have
    checks to make sure you pass in a model and a name. I can do this in Python
    very easily. This code now works as well, but I certainly don't want to not
    use best practices, so how would this be done otherwise?
    Does that not strike you as being horribly complicated for the job it
    seems to be doing? map[string]interface{} is very flexible but what you
    have above is basically using it as a struct where every field access
    needs a type assertion.

    Here's my version of your code.

    package main

    import (
    "fmt"
    )

    type Device struct{
    Name string
    Model string
    Vendor string
    Memory int32
    Cpu int
    }

    // the defaults are just default Device values, so we may as well
    // use the Device structs we already have.
    var defaults = map[string]Device{
    "S93432": Device{
    Vendor: "Sager",
    Memory: 16384,
    Cpu: 2},
    "T40": Device{
    Vendor: "Ibm",
    Memory: 2048,
    Cpu: 1},
    }

    // Instead of a method may we well use a function that is given
    // a possibly incomplete device and fills in the missing fields
    // from the defaults.
    func Init(d Device) Device {
    // if there's no default for the model then we'll get the
    // zero device value, which is OK. If it matters use the
    // two-result version of [] and complain if there's no value
    defaultDevice := defaults[d.Model]
    // check each defaultable value and copy from default
    if d.Cpu == 0 { d.Cpu = defaultDevice.Cpu }
    if d.Memory == 0 { d.Memory = defaultDevice.Memory }
    if d.Vendor == "" { d.Vendor = defaultDevice.Vendor }
    return d
    }

    func main() {
    // Make a (possibly partial) Device and fill it in from the defaults as per
    // Init
    d := []Device{Init(Device{Model: "T40", Name: "ultralight", Cpu:
    2, Memory: 4096})}
    fmt.Println(d)
    }

    No interface{}, no type assertions, no strconv, no keyinlist.

    Chris

    --
    Chris "allusive" Dollin
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Chris dollin at Jun 2, 2015 at 2:59 pm

    On 2 June 2015 at 15:39, Tim Epkes wrote:
    Thanks I'll give that a go. It seem complicated in Go, but in Python it
    makes things extremely easy.
    You pay a penalty for that apparent ease, both in run-time and
    late error detection. Languages have their own strengths and
    weaknesses; one has to play along them, not across them.
    I see what you've done there, I'll try that
    and see if that works. That may be more efficient. I guess the question
    then is, if interface{} is a bad practice/not recommended, why is it there?
    It's there for the times when its a good thing, eg passing arbitrary
    arguments to fmt.Println/Printf or a database etc.

    Chris

    --
    Chris "allusive" Dollin

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim Epkes at Jun 2, 2015 at 7:05 pm
    Thanks Chris and Brendan, that was very helpful.

    Tim
    On Tue, Jun 2, 2015 at 10:59 AM, chris dollin wrote:
    On 2 June 2015 at 15:39, Tim Epkes wrote:
    Thanks I'll give that a go. It seem complicated in Go, but in Python it
    makes things extremely easy.
    You pay a penalty for that apparent ease, both in run-time and
    late error detection. Languages have their own strengths and
    weaknesses; one has to play along them, not across them.
    I see what you've done there, I'll try that
    and see if that works. That may be more efficient. I guess the question
    then is, if interface{} is a bad practice/not recommended, why is it
    there?

    It's there for the times when its a good thing, eg passing arbitrary
    arguments to fmt.Println/Printf or a database etc.

    Chris

    --
    Chris "allusive" Dollin
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJun 1, '15 at 2:50p
activeJun 2, '15 at 7:05p
posts20
users8
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase