Is it possible to convert from type to another type


(AkezhanOb1) #1

I have a type

 type firstType struct {
          Id                   int64    `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`   
          Name                 string   `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
         XXX_NoUnkeyedLiteral struct{} `json:"-"`
         XXX_unrecognized     []byte   `json:"-"`
         XXX_sizecache        int32    `json:"-"`
 }

Is it possible to convert this type into this one

type secondType struct {
  ID   int    `json:"id"`
  Name string `json:"name"`
}

(Ignacio Gómez) #2

In short, no, but give a read to the conversions section here. This is of particular interest:

A non-constant value  `x`  can be converted to type  `T`  in any of these cases:

* `x`  is [assignable](https://golang.org/ref/spec#Assignability) to  `T` .
* ignoring struct tags (see below),  `x` 's type and  `T`  have [identical](https://golang.org/ref/spec#Type_identity) [underlying types](https://golang.org/ref/spec#Types).
* ignoring struct tags (see below),  `x` 's type and  `T`  are pointer types that are not [defined types](https://golang.org/ref/spec#Type_definitions), and their pointer base types have identical underlying types.
* `x` 's type and  `T`  are both integer or floating point types.
* `x` 's type and  `T`  are both complex types.
* `x`  is an integer or a slice of bytes or runes and  `T`  is a string type.
* `x`  is a string and  `T`  is a slice of bytes or runes.

Of course, this is the obvious way of going from one to the other:

//let's say ft is a firstType var
st := secondType{
 ID: ft.Id,
 Name: ft.Name,
}

If you need to do these regularly, maybe a method or function would be of help:

func (ft firstType) Marshal() (secondType, err) {
  //Make some checks on ft fields if you need to.
  return secondType{
   ID: ft.Id,
   Name: ft.Name,
 }, nil
}

(Johan Dahl) #3

Good examples. But why do you return an error from the Marshal function. Is it because some future error if the input isn’t convertible?


(Ignacio Gómez) #4

No special reason really, just in case he wanted to handle some checks. This is just an example:

func (ft firstType) Marshal() (secondType, err) {
  //For some reason, name can't be empty and id must be greater than 0.
  if ft.Name == "" {
    return secondType{}, errors.New("name must be set")
  }
  if ft.Id <= 0 {
    return secondType{}, errors.New("id must be greater than 0")
  }
  return secondType{
   ID: ft.Id,
   Name: ft.Name,
 }, nil
}

But of course, this is just fine (and alternatives using pointers, or a function instead of a method, etc., too):

func (ft firstType) Marshal() (secondType) {
  return secondType{
   ID: ft.Id,
   Name: ft.Name,
 }
}