Where put receivers (methods) in Go? [closed] - go

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
There is a recommended way where put receivers in Go when we have multiple structs in one file?
Option A: Methods after each struct
Buyer struct {
// omitted code
}
func (s *Buyer) Buy() {
// omitted code
}
Seller struct {
// omitted code
}
func (s *Seller) Sell() {
// omitted code
}
Option B: Methods after all structs
Buyer struct {
// omitted code
}
Seller struct {
// omitted code
}
func (s *Buyer) Buy() {
// omitted code
}
func (s *Seller) Sell() {
// omitted code
}

The language spec allows you to put them anywhere in the same package (you can put them in different files too but must be in the same package). Spec: Method declarations:
A receiver base type cannot be a pointer or interface type and it must be defined in the same package as the method.
Other than that it's just common sense. Put them close (next) to the receiver type (which is Option A in your question). Easier to find, easier to maintain.

Related

How can I (or should I) use Go interfaces for picking one of two packages? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
OK, I'm not quite getting it....
I have 2 modules I crafted with identical functions (in different files of course):
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
package mod2
func MyFunc() string {
return "mod2.MyFunc"
}
func Func2() string {
return "mod2.Func2"
}
I have an interface defined correctly, (I think) in a third package:
package types
type MyType interface {
MyFunc() string
Func2() string
}
I have code which can pick whether I want to use mod1 or mod2, but I'm not quite understanding what I should have this code return:
func mypicker() ????{
}
Then in main, I want to somehow call either mod1.MyFunc() or mod2.MyFunc() based on
mypicker, without knowing which it is.... something like this:
func main() {
p := mypicker()
fmt.Print(p.MyFunc())
// and later
fmt.Print(p.Func2())
}
I read that interfaces are like void *, but clearly I'm not getting the complete picture.
Pointers to docs, code, anything useful would be great.
Interfaces should be used with types, not just plain functions. You can start by reading the Tour of Go sequence on interfaces. Here's an example close to your question's original code:
Given the interface:
type MyType interface {
MyFunc() string
Func2() string
}
You'd have a type:
type MyType1 struct{}
func (mt MyType1) MyFunc() string {
return "MyType1.MyFunc"
}
func (mt MyType1) Func2() string {
return "MyType1.Func2"
}
And similarly:
type MyType2 struct{}
func (mt MyType2) MyFunc() string {
return "MyType2.MyFunc"
}
func (mt MyType2) Func2() string {
return "MyType2.Func2"
}
And now, if you have some function that takes your MyType interface:
func Foo(m MyType) {
fmt.Println(m.Func2())
fmt.Println(m.MyFunc())
}
You could call it with either of your types that implements that interface:
m1 := MyType1{}
Foo(m1)
m2 := MyType2{}
Foo(m2)
Here's a Go Playground link where you can try this in action.
As for "picking a type", perhaps you mean something like this:
var mi MyType
if (... some condition ...) {
mi = m1
} else {
mi = m2
}
// Now you can do with mi whatever its interfaces permits,
// like calling mi.Func2(), etc.
Regarding the "picking one of two packages" part of the question:
Interfaces are implemented by types; they're orthogonal to packages and modules. In other words, an interface and types that implement it can all be in the same package, or in different packages, or in different modules.
You have to be careful with terminology. Go modules and Go packages are very different, even though both can be contained by directories. Basically, a directory is a package if it has at least one Go file in it and no go.mod file. If a directory has a go.mod file in it then it's recognized as a module. Generally, a whole project can be a single module with the go.mod file at the root of the project and that's sufficient. Assuming this is your case, move forward thinking that every sub-directory is just a package within that single module.
An interface doesn't really have to do with modules or packages, it has to do with types. The reason being is that an interface defines behavior, meaning it defines what methods are required for a type to accurately implement that interface. In your case, you defined both functions declared in your interface BUT they are NOT METHODS because they are top-level functions only attached to the package. In order for a function to be a method, it must be "attached" to a type. Then, that type becomes a valid implementation of that interface.
This...
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
Needs to become this...
package mod1
type MyTypeImpl struct {}
func (m MyTypeImpl) MyFunc() string {
return "mod1.Myfunc"
}
func (m MyTypeImpl) Func2() string {
return "mod1.Func2"
}
The naming could be improved greatly but the point is that the above function declaration syntax is how you "attach" a function to a type, making it a method, which allows that MyTypeImpl struct to now be a valid implementation of your MyType interface.
Now you can call the interface methods without regards to which underlying type is actually the implementation:
var iType MyType
iType = MyTypeImpl{}
iType.MyFunc()
Notice that in that last line, it does not matter that we used MyTypeImpl to implement the interface. Once the implementation is assigned to a variable with the interface type, we just work with the interface and forget the underlying implementation. When we call iType.MyFunc(), Go will call the proper method from the underlying implementation.
If we had 100 different structs that implemented the MyType interface as MyTypeImpl does, they could all work for the right side of that iType = MyTypeImpl{} line. That's the point of an interface, to define it once and then use it without regard to what underlying struct is actually implementing it.

How to receive publishTime [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a GC function in Go, It is triggered by pubsub push subscription to a topic. I am trying to receive the publishTime and it does not appear populated.
The specs say string (Timestamp format), however, that field in my model is empty. Every other piece of information is populated except publishTime.
type PubSubMessageModel struct {
Data []byte `json:"data"`
Attributes map[string]string `json:"attributes"`
PublishTime string `json:"publishTime"`
}
Simply trying to log the property;
log.Info().Msgf("Publish Time is - %s\n", m.PublishTime)
results in an empty string:
Publish Time is -
Any suggestions?
It's not very well documented, but it is.
The event structure is different when you have a push to the function directly compare to a push Subscription with a HTTP triggered function.
Instead, you can access publishTime and messageId via the event ID and timestamp properties of the event metadata. This metadata is accessible via the context object that is passed to your function when it is invoked.
In the background context description, in Go, there is an explanation of the package to use (functions/metadata) to get the context values
Here how to achieve this
Perform a go get cloud.google.com/go
Use this dependency in your code and get the message metadata from the context
import (
"cloud.google.com/go/functions/metadata"
"context"
"log"
)
type PubSubMessage struct {
Data []byte `json:"data"`
}
// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m PubSubMessage) error {
meta,err := metadata.FromContext(ctx)
if err != nil {
log.Println(err)
return err
}
log.Printf("publishTime, %s", meta.Timestamp)
log.Printf("messageId, %s", meta.EventID)
log.Printf("Type, %s", meta.EventType)
log.Printf("Resource, %s", meta.Resource)
return nil
}

Passing in a different parameter type than the one specified works in Golang? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have 3 packages total: repository, restrict, and main.
In my repository package, I have a structure called "RestrictionRuleRepository" defined as:
type RestrictionRuleRepository struct {
storage map[string]float64
}
In another package restrict, I have a "NewService" function defined:
func NewService(repository rule.Repository) Service {
return &service{
repository: repository,
}
}
Finally, in my package main, I have these two lines of code:
ruleRepo := repository.RestrictionRuleRepository{}
restrictionService := restrict.NewService(&ruleRepo)
My code is compiling without any errors. Why is this allowed in Golang? Doesn't my NewService function expect a Repository type, but I am passing in the address of a RestrictionRuleRepository struct to it?
Most likely rule.Repository is an interface and the *RestrictionRuleRepository type just happens to implement that interface.
Here is an example:
package main
import (
"fmt"
)
type Repository interface {
SayHi()
}
type RestrictionRuleRepository struct {
storage map[string]float64
}
func (r *RestrictionRuleRepository) SayHi() {
fmt.Println("Hi!")
}
type service struct {
repository Repository
}
type Service interface {
MakeRepoSayHi()
}
func NewService(repository Repository) Service {
return &service{
repository: repository,
}
}
func (s *service) MakeRepoSayHi() {
s.repository.SayHi()
}
func main() {
ruleRepo := RestrictionRuleRepository{}
restrictionService := NewService(&ruleRepo)
restrictionService.MakeRepoSayHi()
}
This compiles fine as you can see in https://play.golang.org/p/bjKYZLiVKCh.
I also recommend https://tour.golang.org/methods/9 as a good place to get started with interfaces.

how to use function of unexported struct [duplicate]

This question already has an answer here:
Is there a way to create a function using unexported type as parameter in Golang?
(1 answer)
Closed 3 months ago.
I have a package where I have unexported struct and exported New function to create it and exported function that runs on this struct (as advised for example here: Return an unexported type from a function).
If I run the function in the same place the New is called I can run the package function but I am unable to send this entity to another function.
what is the best way to achieve this behavior without the need to have all my code in one function
this for example works:
client := package.New()
client.Foo()
but this cannot work:
client := package.New()
hello(client)
func hello(client interface{}) {
client.Foo()
}
What your hello function essentially needs is something that has a Foo function. That's why go has interfaces. There's nothing wrong with returning an unexported type (in fact, it's common and often the right thing to do). What I'd do is this:
package foobar
// whatever thing that has a Foo function
type FClient interface {
Foo()
}
func Hello(client FClient) {
client.Foo() // will work
}
The reason why you'd do it like this is to be able to unit-test this code:
package foobar_test
import (
"testing"
)
type testFC struct {
callCount uint64
}
// implement interface
func (t testFC) Foo() {
testFC.callCount++
}
func TestHello(t *testing.T) {
client := testFC{}
Hello(client)
if client.callCount != 1 {
t.Fail("dependency not called")
}
}
Of course, for more complex dependencies you'd use tools like mockgen or stuff like that, but you get the idea. By definition, a UNIT test focuses on a single UNIT of code. The last thing you'd need to do to test a package unit is to instantiate a type from another package. You should be able to mock everything your code depends on. The best way to do so is interfaces.

"Perfect singleton" via using sync.Once? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
i am confusing that, is below snippet perfect?
import "sync"
import "sync/atomic"
var initialized uint32
var instance *singleton
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
atomic.StoreUint32(&initialized, 1) will flush instance to all CPUs?
i think i need add an atomic store and load for instance, like below snippet
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
atomic.StorePointer(&instance, &singleton{})
})
return atomic.LoadPointer(&instance)
}
i think Once.Do is only guarantee execute function f one time.
and atomic.StoreUint32(&o.done, 1) is only memory barrier for o.done.
it doesn't ensure instance is global visible
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
Lets break down your question to two pieces:
Singletons
Atomics and the Go memory model
Singletons
Go has package level variables. These are instantiated before anything has the chance to get moving, therefore if you good with these things being created as soon as the package is used, you get a singleton for free.
package somepack
var(
connection = createConn()
)
func Connection() SomeConnection {
return connection
}
connection will be created once and therefore Connection() will return the same instance of it safely.
Sometimes developers reach for a singleton when they want "lazy" instantiation. This is a good idea if the resource is expensive to create and not always needed. This is where sync.Once is useful.
var (
connection SomeConnection // Not instantiated
connectionOnce sync.Once
)
func Connection() SomeConnection {
connectionOnce.Do(func(){
connection = createConn()
})
return connection
}
Notice I'm not doing anything special with the assignment (e.g., atomic.Store()). This is because sync.Once takes care of all the locking required for this to be safe.
Atomics and the Go memory model
A good resource to start with is the published docs for this: The Go Memory Model
Your concern of "flushing" to the different CPUs is valid (despite some of the comments) because each CPU has its own cache with its own state. C++ (among other languages like Rust) developers tend to care about this because they get to. Go developers don't get to care AS much because Go only has "happens before". Rust in fact has some nice docs on it.
That being said, you normally don't need to worry about it. A mutex (and sync.Once) will force the state of the memory on each CPU to be what you would expect.

Resources