Allow pass to func only pointer, not values - go

I want to allow pass to func only pointer to a struct, restrict values. Is it possible?
What I want to do:
Foo(&Bar{}) // allowed
Foo(Bar{}) // IDE/compilation error
Actually i'm using signature like func Foo(bar any) which allows pass to the function any interface and type, of course, so in some cases it can cause problems.
Amount of types, which can passed to this function is should be not limited, and I don't want to use specific interface etc. Maybe this can be achieved with generics? But I'm not sure how to do it correctly.
I'm use go 1.18.

Yes you can use generics like this:
func Foo[T any](t *T){
…
}

Related

Can I create an alias of a type in Golang?

I'm struggling with my learning of Go.
I found this neat implementation of a Set in go: gopkg.in/fatih/set.v0, but I'd prefer naming my sets with a more explicit name that set.Set, doing something like:
type View set.Set
In essence, I want my View type to inherit set.Set's methods. Because, well, View is a set.Set of descriptors. But I know Go is pretty peaky on inheritance, and typing in general.
For now I've been trying the following kinda inheritance, but it's causing loads of errors when trying to use some functions like func Union(set1, set2 Interface, sets ...Interface) Interface or func (s *Set) Merge(t Interface):
type View struct {
set.Set
}
I'd like to know if there's a way to achieve what I want in a Go-like way, or if I'm just trying to apply my good-ol' OO practices to a language that discards them, please.
If anyone else is coming back to this question, as of Go 1.9 type aliases are now supported.
A type alias has the form: type T1 = T2
So in your example you can just do type View = set.Set and everything will work as you want.
Note, I think the simple aliasing you proposed initially is syntactically valid though having had a quick look at the set library, rather than aliasing set.Set it might make more sense to alias set.Interface, e.g.:
package main
import (
"fmt"
set "gopkg.in/fatih/set.v0"
)
// View is a type alias for the set.Interface interface
type View set.Interface
// Display takes one of our View types in order to print it.
func Display(view View) {
fmt.Println(view.List())
}
func main() {
// create our first set.Interface or View
v1 := set.New()
v1.Add("foo")
// create our second set.Interface or View
v2 := set.New("bar")
// call a set function
v3 := set.Union(v1, v2)
// call our function that takes a View
Display(v3)
}
You may have noticed I'm cheating somehow because I make no real mention of the aliased type in the above code other than in defining the parameter to the Display function above which you'll note takes in a View instance rather than a set.Interface. If you have lots of functions working on these things, then that might read more expressively for your domain.
Note that because our View type is an alias to an interface type, it precludes adding your own functions to that type as Go doesn't allow us to have an interface receiver type for a function (I might be expressing that incorrectly). By this I mean that you can't do anything like:
func (v View) Display() string {
return v.String()
}
In summary I think aliasing things is fine, it can make internal APIs more readable, and you can lean on the compiler to help eliminate certain classes of errors; however this doesn't allow you to add functionality to the custom type. If this is required an alternate approach would be necessary, either embedding or simple composition (i.e. a View has a Set).

Best practices to use own type in golang. Alians to build type

I wonder when or if it should be use own type in golang. When this will be more friendly to understand my code, or when I shouldn't use own type.
Example:
I want to create map type with MAC, and name host:
in first way the simplest I can do that
var machines map[string]string{
"11:22...": "myHost",
"22:33..": "yourHost",
}
in second way
type MAC string
type HOST string
machines := map[MAC]HOST{
MAC("11:22..") : HOST("myHost"),
MAC("22:33..") : HOST("yourHost"),
}
In above exmaple I can get additional controle on my type MAC, HOST trought write method to validation, compare etc it is better ?
Third way
type MACHINES map[string]string
m := MACHINES{}
m = map[string]string{
"11:22.." : "myHost",
"22:33" : "yourHost",
}
above example for me is worst to understand less intuitive to some else. I think that above example should be also filled about HOST, and MAC because type MACHINE nothing to say developer how this should be implement so I would like
type MACHINES map[MAC]HOST
However, please about comment to better understand about usage own type in golang.
Without commenting on your specific example, there are a few reasons you'd generally want to use a new type:
You need to define methods on the type
You don't want the type to be comparable with literals or variables with the type it's derived from (eg. to reduce user confusion or make sure they don't do something invalid like attempt to compare your special string with some other random string)
You just need a place to put documentation, or to group methods that return a specific type (eg. if you have several Dial methods that return a net.Conn, you might create a type Conn net.Conn and return that instead just for the sake of grouping the functions under the Conn type header in godoc or to provide general documentation for the net.Conn returned by the methods).
Because you want people to be able to check if something of a generic type came from your package or not (eg. even if your Conn is just a normal net.Conn, it gives you the option of type switching and checking if it's a yourpackage.Conn as well)
You want a function to take an argument from a predefined list of things and you don't want the user to be able to make new values that can be passed in (eg. a list of exported constants of an unexported type)
Creating type alias is only useful when you require to add extra methods (such as validation functions) or when you want to document the desired use of some value (for example, the net.IP type).
Type alias could help you to prevent API misunderstanding, but won't if you're using constant values. For example, this code is valid:
type Host string
type Mac string
hosts := map[Mac]Host{"ad:cb..": "localhost"}
For further information about how constants work in Go, you can check the Rob Pike's blog post
One of the most important features of Go is interfaces. In Go by defining the method/s of an Interface you implement the interface, and the only way to implement an interface is by adding a Method to your type. For instance, say you want to implement the Stringer interface from the fmt package.
In your example type MACHINES map[string]string you would add a method called String to your type.
func (m MACHINES) String() string {
s := "MACHINES\n"
for k, v := range m {
s += fmt.Sprintf("%v: %v\n", k, v)
}
return s
}
Any other function that accepts the Stringer interfaces can now also accept your MACHINES type since you implemented the Stringer interface.
For example the fmt.Printf checks if the passed in type implements the Stringer interface
m := MACHINES{"foo":"bar", "baz": "bust"}
fmt.Printf("%s", m)
Will invoke MACHINES String method
Example from the playground
You do want to use your own types in my opinion.
As an example, lists of function arguments that are all "string" or all "int" are confusing and very easy to get wrong.
And a comment on your type names. "MAC" is an acronym for Media Access Control so it should stay as all caps. But "HOST" should be "Host" since it is just a word. I don't recall where it is exactly, but there's a recommended form for Go names which is CamelCase with all-capital abbreviations, like "GetIPv4AddressFromDNS"
I think another reason to use your own types, that hasn't been mentioned here, is if you are not sure exactly what the right type for something is e.g. uint8 / uint16 and you want to easily change it later all in one place.
This will however make conversions necessary whenever you want to use the built-in types' methods. Or you will need to define them on your own type.

Why do packages export a non-exported function by returning the non-exported function through an exported function

Why do some packages declare two equal functions the only difference is one is exported and the other is not but the one that is exported just returns the non-exported function like this:
func Foo() {
return foo()
}
func foo() {
log.Println("Hello")
}
Why not just move the log into the exported function and get rid of the extra line? Obviously there is a reason but I don't really see one if you can just use the exported one everywhere. Thanks!
Example here of it being used in Production
You mentioned a couple examples. The first example (https://github.com/yohcop/openid-go/blob/master/verify.go#L11-L13):
func Verify(uri string, cache DiscoveryCache, nonceStore NonceStore) (id string, err error) {
return verify(uri, cache, urlGetter, nonceStore)
}
You can see that the unexported verify function takes an extra urlGetter argument. This may be something that a client of this package cannot or should not provide. The exported function determines how clients of the package can/should use it; the signature of the non-exported function reflects the dependencies required to do whatever business logic verify is doing.
The second example(https://github.com/golang/oauth2/blob/master/oauth2.go#L259-L266):
func StaticTokenSource(t *Token) TokenSource {
return staticTokenSource{t}
}
// staticTokenSource is a TokenSource that always returns the same Token.
type staticTokenSource struct {
t *Token
}
This restricts how clients can construct the staticTokenSource: there is only one way to do it, via the StaticTokenSource constructor, and it cannot be done directly via a struct literal. This can be useful for many reasons, e.g. input validation. In this case, you want the safety of knowing that the client cannot mutate the t field on the object, and in order to do this, you leave the t field unexported. But when it's unexported, the client will not be able to construct the struct literal directly, so you must provide a constructor.
In general, it makes your code much easier to reason about when you can restrict how things are accessed, constructed, or mutated. Golang packages give you a nice mechanism to encapsulate modules of business logic. It's a good idea to think about the conceptual components of your software, and what their interfaces should be. What really needs to be exposed to client code consuming a given component? Only things that really need to be exported should be.
Further reading: Organizing Go code

Designing Go packages: when I should define methods on types?

Suppose that I have a type type T intand I want to define a logic to operate on this type.
What abstraction should I use and When ?
Defining a method on that type:
func (T t) someLogic() {
// ...
}
Defining a function:
func somelogic(T t) {
// ...
}
Some situations where you tend to use methods:
Mutating the receiver: Things that modify fields of the objects are often methods. It's less surprising to your users that x.Foo will modify X than that Foo(x) will.
Side effects through the receiver: Things are often methods on a type if they have side effects on/through the object in subtler ways, like writing to a network connection that's part of the struct, or writing via pointers or slices or so on in the struct.
Accessing private fields: In theory, anything within the same package can see unexported fields of an object, but more commonly, just the object's constructor and methods do. Having other things look at unexported fields is sort of like having C++ friends.
Necessary to satisfy an interface: Only methods can be part of interfaces, so you may need to make something a method to just satisfy an interface. For example, Peter Bourgon's Go intro defines type openWeatherMap as an empty struct with a method, rather than a function, just to satisfy the same weatherProvider interface as other implementations that aren't empty structs.
Test stubbing: As a special case of the above, sometimes interfaces help stub out objects for testing, so your stub implementations might have to be methods even if they have no state.
Some where you tend to use functions:
Constructors: func NewFoo(...) (*Foo) is a function, not a method. Go has no notion of a constructor, so that's how it has to be.
Running on interfaces or basic types: You can't add methods on interfaces or basic types (unless you use type to make them a new type). So, strings.Split and reflect.DeepEqual must be functions. Also, io.Copy has to be a function because it can't just define a method on Reader or Writer. Note that these don't declare a new type (e.g., strings.MyString) to get around the inability to do methods on basic types.
Moving functionality out of oversized types or packages: Sometimes a single type (think User or Page in some Web apps) accumulates a lot of functionality, and that hurts readability or organization or even causes structural problems (like if it becomes harder to avoid cyclic imports). Making a non-method out of a method that isn't mutating the receiver, accessing unexported fields, etc. might be a refactoring step towards moving its code "up" to a higher layer of the app or "over" to another type/package, or the standalone function is just the most natural long-term place for it. (Hat tip Steve Francia for including an example of this from hugo in a talk about his Go mistakes.)
Convenience "just use the defaults" functions: If your users might want a quick way to use "default" object values without explicitly creating an object, you can expose functions that do that, often with the same name as an object method. For instance, http.ListenAndServe() is a package-level function that makes a trivial http.Server and calls ListenAndServe on it.
Functions for passing behavior around: Sometimes you don't need to define a type and interface just to pass functionality around and a bare function is sufficient, as in http.HandleFunc() or template.Funcs() or for registering go vet checks and so on. Don't force it.
Functions if object-orientation would be forced: Say your main() or init() are cleaner if they call out to some helpers, or you have private functions that don't look at any object fields and never will. Again, don't feel like you have to force OO (à la type Application struct{...}) if, in your situation, you don't gain anything by it.
When in doubt, if something is part of your exported API and there's a natural choice of what type to attach it to, make it a method. However, don't warp your design (pulling concerns into your type or package that could be separate) just so something can be a method. Writers don't WriteJSON; it'd be hard to implement one if they did. Instead you have JSON functionality added to Writers via a function elsewhere, json.NewEncoder(w io.Writer).
If you're still unsure, first write so that the documentation reads clearly, then so that code reads naturally (o.Verb() or o.Attrib()), then go with what feels right without sweating over it too much, because often you can rearrange it later.
Use the method if you are manipulating internal secrets of your object
(T *t) func someLogic() {
t.mu.Lock()
...
}
Use the function if you are using the public interface of the object
func somelogic(T *t) {
t.DoThis()
t.DoThat()
}
if  you want to change T object, use
func (t *T) someLogic() {
// ...
}
if you donn't change T object and would like a origined-object way , use
func (t T) someLogic() {
// ...
}
but remeber that this will generate a temporay object T to call someLogic
if your like the way c language does, use
func somelogic(t T) {
t.DoThis()
t.DoThat()
}
or
func somelogic(t T) {
t.DoThis()
t.DoThat()
}
one more thing , the type is behide the var in golang.

How do you typecast a map in Go into a custom type?

I have a custom type defined:
type Thingy map[string]interface{}
and I have a function that is passed an empty interface argument:
func f(arg interface{})
What I'd like to do is be able to typecast arg into a variable of type Thingy. I must be misunderstanding something fundamental about Go because I can't get this to work:
t, ok := arg.(Thingy)
ok always returns false there. Any ideas? Full example here: http://play.golang.org/p/TRZsX4v8-S
That's not a cast, but a type assertion.
You're not passing a Thingy, but a map[string]interface{}
It's important to understand that just because types look similar, that doesn't mean you can use them interchangeably. This is most important when there are method sets. A call to x() on two different types have to be distinguishable even if the underlying types are the same.

Resources