Any way to alias a function name to '_'? - go

In Go, is there any circumstance where the gettext short-form of:
_("String to be translated.")
can be used? One of those times where I'm fairly certain the answer is 'no', but asking just in case I've overlooked something. I'm thinking the best that can be achieved is:
import . "path/to/gettext-package"
...
s := gettext("String to be translated.")
since underscore has a very specific meaning, and attempting to define a function named '_' results in the compile-time error "cannot use _ as value".

No. The blank identifier
... does not introduce a new binding.
IOW, you can declare "things" named _ but you cannot refer to them in any way using that "name".
However, one can get close to the goal:
package main
import "fmt"
var p = fmt.Println
func main() {
p("Hello, playground")
}
(also here)
ie. you can bind any (local or imported) function to a variable and later invoke the function through that variable, getting rid of the package prefix - if you think that's handy. IMO not, BTW.

Related

Go Doc is indenting/grouping functions unexpectedly. What is causing it?

Go Doc is indenting/making a group without me knowingly telling it to.
Here is a screenshot from my browser showing the problem. The four Parse functions should not be indented:
What is causing this behaviour?
I've tried searching for indents/subsections/grouping in Go Docs but I've not found anything beside feature requests. I'm sure the answer to my question is in the documentation somewhere but I can't find it as I don't have the correct vocabulary.
I'm relatively new to Go and Go Doc, so I'm assuming the answer is something simple which I've overlooked.
Here is an extract of my code. Please let me know if I need to share more code.
status.go
package synop
// Status codes returned when parsing Blocks.
type Status int64
const (
VALID Status = iota
NO_DATA
// code omitted
)
// Other functions omitted
cloudwind_block.go
package synop
import (
"strings"
)
/*
Extract cloud cover from the cloud-wind block, Cxxxx.
Cloud, C, is the first digit of the block. Cloud over is given in [okta]:
*/
func ParseCloud(block string) (okta int, s Status) {
slice := [2]int{0, 1}
return parseIfValid(block, slice, str2int)
}
/*
Extract wind direction from from the cloud-wind block, xDDxxx.
Direction, DD, are the second and third digits.
*/
func ParseDir(block string) (dir string, s Status) {
slice := [2]int{1, 3}
return parseIfValid(block, slice, getDir)
}
// Other functions omitted
I have another file, blocks.go, which has almost the same structure as status.go and it does not cause this behaviour. I also don't know if the problem is caused by the preceding type Status or something in the cloudwind_block.go file.
I'm using // for single-line documentation and /* */ for multi line. I've tried making this consistent on the off chance and, as expected, it had no effect.
The reason for the grouping and indentation is that those functions are considered "constructors" of the type under which they are grouped/indented.
https://go.dev/doc/comment#func (if you scroll down a bit, you'll see this):
This example also shows that top-level functions returning a type T or pointer *T, perhaps with an additional error result, are shown alongside the type T and its methods, under the assumption that they are T’s constructors.

Passing function as parameter: Incompatible types in Golang

Fairly new to Go, but still no idea why this isn't working. There's a function (A) being defined and passed as argument to another function (B), which takes A's arguments in the exact correct way (AFAIK):
// Function A
func writeToPumps(keys []interface{}, job *health.Job, startTime time.Time) {..}
// Function B
func GenerateDemoData(start time.Time, days int, orgId string, writer func(keys []interface{}, job *health.Job, startTime time.Time)) {...}
//calling Function B with Function A as last argument:
demo.GenerateDemoData(time.Now().AddDate(0, 0, -30), 30, buildDemoData, writeToPumps)
That yields:
./main.go:191:56: cannot use writeToPumps (type func([]interface {}, *"tyk-pump/vendor/github.com/gocraft/health".Job, time.Time)) as type func([]interface {}, *"github.com/TykTechnologies/tyk-pump/vendor/github.com/gocraft/health".Job, time.Time) in argument to demo.GenerateDemoData
How can I fix this?
EDIT
Import section in main.go:
import (
"github.com/TykTechnologies/tyk-pump/analytics/demo"
"time"
"os"
"fmt"
"github.com/gocraft/health"
"gopkg.in/vmihailenco/msgpack.v2"
"github.com/TykTechnologies/logrus"
"github.com/TykTechnologies/logrus-prefixed-formatter"
"github.com/TykTechnologies/tyk-pump/analytics"
"github.com/TykTechnologies/tyk-pump/pumps"
"github.com/TykTechnologies/tyk-pump/storage"
"github.com/TykTechnologies/tykcommon-logger"
"gopkg.in/alecthomas/kingpin.v2"
)
Other useful info:
GOPATH: /home/nilsnolde/dev/go/uni
Project structure:
../uni/src/
|
--tyk-pump/
|
--vendor/
main.go
...
Your code should live under /uni/src/github.com/TykTechnologies/tyk-pump. Since it doesn't, when your code internally references that package hierarchy, it re-vendors your code, generating duplicate import paths.
So the fix is probably just to move /uni/src/tyk-pump to /uni/src/github.com/TykTechnologies/tyk-pump then re-import all your vendored packages.
The file in which function A is defined is likely not the same file where you have B defined. The two files are both importing health, where the definition of health.Job seems to live.
However they seem to be using a different import path, therefore GO thinks that the definition of health.Job isn't the same.
You should check the import statements in both places and make them the same. If they are already the same, there is something in the project setup that needs to be adjusted, but there isn't enough context to figure out what that might be.

Is it possible to use only one of the return values when initializing members in Go?

I understand how to use multiple return values in go. I further understand that in most cases one of the returns is an error, so ignoring returned values can be dangerous.
Is there a way to ignore a value in struct initializer like this? The below example does not work as Split returns two values, but I am interested only in the first one. I can of course create a variable but...
someFile := "test/filename.ext"
contrivedStruct := []struct{
parentDir string
}{
{ parentDir: filepath.Split(someFile) },
}
It's not possible to use only one of the return values when initializing members in Go.
Using variables clearly expresses your intent.
Go sometimes feels like it could be more succinct, but the Go authors favoured readability over brevity.
Alternatively, use a wrapper function. There are several 'Must' wrapper functions in the standard library, like: template.Must.
func first(args ...string) string {
return args[0]
}
For your particular example, splitting paths, see filepath.Base or filepath.Dir.
No, there is no way to skip one of the returned values in structure initializer.

Function parameter error - Missing Argument Label Anomaly - SWIFT

I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?

Is there any tangible downside to using static type constructors in go?

I've always found the package.New() syntax in go rather awkward to work with.
The suggestion is that if a package holds only a single type, using package.New() to create an instance; if multiple types exist, using package.NewBlah().
http://golang.org/doc/effective_go.html#package-names
However, this approach falls down if you if you have an existing package with a New() api, adding a new external type to the package breaks the api, because you must now rename this NewFoo(). Now you have to go and change anything that uses New(), which is deeply irritating.
...and I'm just discontent with the aesthetic of writing this:
import "other"
import "bar"
import "foo"
o := other.New() // <-- Weird, what type am I getting? No idea.
x := bar.New()
y := foo.NewFoo() // <-- Awkward, makes constructor naming look inconsistent
z := foo.NewBar()
So, recently I've been using this pattern instead:
x := foo.Foo{}.New() // <-- Immediately obvious I'm getting a Foo
y := foo.Bar{}.New() // <-- Only an additional 3 characters on NewBar{}
o := other.Foo{}.New() // <-- Consistent across all packages, no breakage on update
Where the module is defined something like this:
package foo
type Foo struct {
x int
}
func (s Foo) New() *Foo {
// Normal init stuff here
return &s // <-- Edit: notice the single instance is returned
}
type Bar struct {
}
func (Bar) New() *Bar {
return &Bar{} // <-- Edit: Bad, results in double alloc. Not like this.
}
Godoc seems to work fine with it, and it seems more obvious and consistent to me, without additional verbosity.
So, question: Is there any tangible downside to this?
Yes, it has a downside. This approach may generate unnecessary garbage - depending on how good the optimization of a specific Go compiler implementation is.
It's not terribly idiomatic and may if done badly create excess garbage as you note. Essentially you are just creating an Init method for your object. I don't use a lot of constructors myself tending to prefer having valid zero values for my objects and only using a constructor if that doesn't hold true.
In your case I think I'd just stop calling the method new and instead call it Init or Setup to better reflect what it's doing. That would avoid giving people the wrong idea about what it's doing.
Edit:
I should have been more detailed here. Calling the method Init or Setup and then using it on a Zero Value would better reflect what is going on to the consumer. eg
f := &foo{}
f.Init()
This avoids the excess garbage and gives you an initializer method as you describe.

Resources