Lee
Lee

Reputation: 8734

Golang type assertion

I have created a type Role based off string, and I am now trying to get it to work with the database driver by implementing the Valuer and Scanner interfaces

type Role string

func (r *Role) Scan(value interface{}) error {
    r = (*Role)(value.(string))

    return nil
}

func (r *Role) Value(value driver.Value, err error) {
    if err != nil {
        value = string(r)
    }
}

I keep getting the error:

The Go code app/entities/user.go does not compile: cannot convert value.(string) (type string) to type *Role

What am I doing wrong here?

Upvotes: 21

Views: 29818

Answers (2)

Max
Max

Reputation: 6394

Here is working code for the first function:

func (r *Role) Scan(value interface{}) error {
    *r = Role(value.(string))
    return nil
}

Although you may wish to use s, ok := value.(string) and return an error for !ok instead of panic-ing.

The signature for the a driver.Valuer is not what you gave but:

func (r Role) Value() (driver.Value, error) {
    return string(r), nil
}

Note this doesn't handle or produce NULL values.

Playground

Upvotes: 24

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657098

I don't think it's a good idea to modify the receiver of your method (r) in the Scan method.

You need a type assertion to convert value interface{} to string.
You are trying to convert a string to a pointer to Role.

func (r *Role) Scan(value interface{}) (retVal Role, err error) {
    var s string;

    if v,ok := value.(string); ok {
      s = v;
    }
    var rx Role
    rx = Role(s)

    var rx2 *Role
    rx2 = &rx
    _ = rx // just to silence the compiler for this demonstration
    _ = rx2 // just to silence the compiler for this demonstration
    return rx, nil
}

should work

Upvotes: 4

Related Questions