cannot define new methods on non-local type models.Meter
Asked Answered
W

2

6

I want to put all my models in a shared Common lib.

So, I made a new repo: gitlab.com/xxx/common

Inside I put a package: models

Here is the definition of an object:

type Meter struct {
    ID           string
    OperationID  string
    Type         ConsoProd
    Unit         string
    Timestep     time.Duration
    Measures     []Measure 
    FetchMethod  AcquisitionMethod
    Metadata     interface{}
}

Now, I want to use it in an external project, I do:

go get gitlab.com/xxx/common

And Go Modules will download it.

I import use it like that:

import "gitlab.com/xxx/common/models"

//String transparent method
func (meter models.Meter) String() string {
    var stringifyMeter string
    stringifyMeter += "Meter " + meter.ID + " is a " + meter.Type.String() + " and compute in operation #" + meter.OperationID + "."
    return stringifyMeter
}

But Goland will not resolve it, and when I compile, I get:

cannot define new methods on non-local type models.Meter

Why is it happening and what can I do to fix it ?

Weather answered 19/7, 2019 at 10:1 Comment(0)
B
9

It is not allowed to define methods outside the package where the type is defined. This leaves you with a couple of options:

  1. Define the methods in the models package. That's the simplest approach when dealing with your own code but of course won't work for 3rd-party types.

  2. Create a regular function instead of a method (func String(meter models.Meter) string). That might be less idiomatic, though (especially for the String method), and also does not have access to private fields (unless you define the function in the models package, in which case you could just define the method instead).

  3. Create a new type embedding the original type. That would be a bit cumbersome to use but allows you to extend existing behavior. Something like this:

`

package main

import (
    "fmt"
    "time"
)

func main() {
    myTime := MyTime{time.Now()}
    fmt.Println(myTime)        /* behaves as time.Time */ 
    fmt.Println(myTime.Foo())  /* also has extra methods */
}

type MyTime struct {
  time.Time
}

func (m MyTime) Foo() string {
  return "foo"
}
Beecher answered 19/7, 2019 at 10:22 Comment(1)
Ok ! Option one make sense ! Thanks for your helpWeather
D
2

Simple,

import ...bla/bla/Meter

type extended Meter

Ref: https://github.com/golang/go/issues/31631#issuecomment-486075295

Disordered answered 5/1, 2021 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.