I am facing an issue with my code and is giving errors:
unnamed and mixed parameters
func(uc fyne.URIWriteCloser, error) {
...
}
It looks like you declared a function that has a named, and an unnamed parameter, which you cannot do.
There are two ways you can handle parameters in a func. You can either name all of the parameters, or provide no names to any of the parameters.
This is a valid func signature with both parameters named.
func(uc fyne.URIWriteCloser, err error) {
// do something
}
And so is this, without naming the parameters.
func(fyne.URIWriteCloser, error) {
// do something
}
If you were to name the first param, but leave the second param unnamed
func(uc fyne.URIWriteCloser, error) {
// do something
}
Then you would see this error
Function has both named and unnamed parameters
So, the problem is that the second param simply declares the param type and not the name, while the first param is defining the type and naming the param.
As specified in the specs for Function Types:
Within a list of parameters or results, the names (IdentifierList) must either all be present or all be absent.
If present, each name stands for one item (parameter or result) of the specified type and all non-blank names in the signature must be unique.
If absent, each type stands for one item of that type.
Parameter and result lists are always parenthesized except that if there is exactly one unnamed result it may be written as an unparenthesized type.
So either remove uc, or add err error.
Related
Given the following proto message
message MyMsg {
string my_field = 1;
string your_field=2;
}
...the protoreflect package can be used to get a descriptor for each field
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf type information
fieldDescriptors := messageDescriptor.Fields() // list of field declarations
Getting a field descriptor for a specific field is trivial
fieldDescriptor := fieldDescriptors.ByTextName("my_field") // describes a field
Can this be achieved without hard-coding the field name "my_field"? I guess it would be nice to use the generated code to refer to the field I'm interested in. Something like (not working code)
fieldDescriptor := fieldDescriptors.ByTextName(pb.MyMsg.MyField) // describes a field
This way, if the field name changes, it will be caught at compile time, or even from static analysis by an IDE.
The FieldDescriptors type has three methods for getting a field descriptor by name:
ByName(s Name)
ByJSONName(s string)
ByTextName(s string)
ByJSONName and ByTextName both require hard-coded field names (as strings), and by ByName accepts a Name which is type'd to a string. The upshot is, I don't see anything in the protoreflect package that points to a solution.
Context
Field masks are the recommended way to support partial resource updates. It's trivial to iterate over the masks provided in a field mask
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf type information
fieldDescriptors := messageDescriptor.Fields() // list of field declarations
// iterate over the field paths in the field mask
for _, p := range mask.GetPaths() {
// find the field descriptor for the field path
fieldDescriptor := fieldDescriptors.ByTextName(p)
if fieldDescriptor == nil {
// field descriptor cannot be found for the field path
return
}
// great, the field path points to a field, let's use it
switch p {
case "my_field":
// the client wants to update MyMsg.my_field
case "your_field":
// the client wants to update MyMsg.your_field
}
}
The problem is, in order to actually update the correct field in MyMsg, it's necessary to hard-code the field name in the switch statement.
The interface has ByNumber too
I assume (I've not used the method) that you could give this 1 from your example.
And Get, of course so that you can enumerate all of the FieldDescriptors.
I think it's not unreasonable to want to reflect (!) the generated (struct) types and enumerate across them but it feels like turtles-all-the-way-down.
It may help solicit other answers if you could present the problem that you're unable to solve without the desired method?
I have a dynamic error message for example
metadata.name: invalid value "test-value"
"test-value" will be dynamic, and I need to do something if this error pattern appears
How to check the errors pattern with Error.Is function?
You say your error has a dynamic message. I think you mean that you're defining a type that satisfies the error interface. (If you're using fmt.Errorf instead though, you should define a type for this use case).
type invalidValueError struct {
value string
}
func (e *invalidValidError) Error() string {
return fmt.Sprintf("invalid value %q", e.value)
}
You can check whether any given error has this type using errors.As. This will match not only the error itself, but any errors it's wrapping.
if ive := (*invalidValueError)(nil); errors.As(err, &ive) {
// got an *invalidValueError
}
Avoid matching the text of error messages if at all possible. They can change on different systems or in different locales, and they're generally not covered by compatibility promises.
I'm trying to understand the Wire library in Golang and find that in the wire.go there's a function looks like this:
func NewSet(...interface{}) ProviderSet {
return ProviderSet{}
}
It looks foreign to me as to why the ...interface{}) parameter is unnamed (meaning not being used inside the function) but then the caller still passes meaningful values to it?
var Set = wire.NewSet(
wire.Value(Foo(41)),
provideFooBar)
Parameters being named or unnamed has nothing to do with whether the caller having to pass values for them. Being unnamed just means they cannot be used (cannot be referred to) inside the function.
NewSet has a variadic parameter, which means any number of arguments may be passed to it that can be assigned to the type, and any value can be assigned to interface{} (all value implements the empty interface).
The "empty" implementation of NewSet() you see is just a placeholder for documentation and compilers. The generated code will use the passed arguments.
If you have a function:
func dummy(int) {}
You can't call it like dummy(), that's a compile-time error. You can only call it by passing an int value to it, e.g. dummy(1).
See related: Is unnamed arguments a thing in Go?
The Go Tour says the following:
You can only declare a method with a receiver whose type is defined in the same package as the method. You cannot declare a method with a receiver whose type is defined in another package (which includes the built-in types such as int).
Is there a reason for this other than avoiding everyone building their own methods off int and string? I've Googled around, but can't find anything referencing it.
The reason is that if you could define methods on other packages' types, you could modify the behavior of other packages. This is because the method set of a given type can have an effect on how values of that type are used.
Consider, for example, the fmt.Println function. When you pass an argument to fmt.Println, it will print a string representation of that value based on a set of rules. One of those rules is that if the type of the value has a String() string method (that is, it implements the fmt.Stringer interface), then that method will be called in order to obtain the string representation of the value.
Thus, imagine that we have a package, foo, and that package has a type, FooInt, defined as follows:
type FooInt int
Now imagine that this package also has a function, PrintFooInt:
func PrintFooInt(f FooInt) { fmt.Println(f) }
This will print the integer value of f. But let's say that you (in a different package, say main) were able to add methods to FooInt. Then you could do this:
func (f FooInt) String() string { return "foobar!" }
This would actually change the behavior of foo.PrintFooInt, which shouldn't be possible from outside the package.
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?