"%!s"-like error in fmt.Printf when format string is from arguments (go language) - go

just see the code:(so simple that I can't believe myself)
package log
import "fmt"
func P(format string,a ...interface{}){
fmt.Printf(format,a)
}
when called somewhere like this :
log.P("%s,%s,%d","","",0)
I got error:
[ %!s(int=0)],%!s(MISSING),%!d(MISSING)
BUT if I call fmt.Printf directly like this:
fmt.Printf("%s,%s,%d","","",0)
It works perfectly,just perfectly (of course,as basic use of fmt).
So the Question is:
Why log.P not work??
FYI:
I believe it's pretty simple ,but I just can't find an answer by google,
never ever someone dropped in the hell ?
Or maybe I just dont know how to ask,so I put pure code above.
Or just I'm a super fool this time?
I signed up stackoverflow today for an answer to this. Let me know what's wrong with me. As soon...

It is just a little mistake. You are calling fmt.Printf with a as a single argument, while it is not. You need to pass it as a variadic argument.
package main
import (
"fmt"
)
func P(format string, a ...interface{}) {
fmt.Printf(format, a)
}
func P2(format string, a ...interface{}) {
fmt.Printf(format, a...)
}
func main() {
P("%s,%s,%d", "", "", 0)
fmt.Println()
P2("%s,%s,%d", "hello", "world", 0)
}
You can read about variadic parameters here.

You need to pass a to Printf as variadic and to convert an array to variadic, you need to follow this notation:
func P(format string, a ...interface{}){
fmt.Printf(format, a...)
}
The Go Programming Language Specification
Passing arguments to ... parameters
If f is variadic with final parameter type ...T, then within the
function the argument is equivalent to a parameter of type []T. At
each call of f, the argument passed to the final parameter is a new
slice of type []T whose successive elements are the actual arguments,
which all must be assignable to the type T. The length of the slice is
therefore the number of arguments bound to the final parameter and may
differ for each call site.

Related

Print type parameter name in Go

If I write a generic function in Golang, I can print the type of either of the arguments to the function like this, which provides some insight into the type parameter:
func foo[T any](a T, b T) string {
return fmt.Sprintf("%v and %v are of type %T", a, b, a)
}
However, if I modify the function to take a slice instead:
func foo[T any](args ...T) string {
return fmt.Sprintf("%+v are of type %T", args, args)
}
this will not print what I would prefer as calling foo[int] will mean that args has a type of []int whereas I want to print int. I could modify this to print args[0] instead but that means I also have to check for the case where args is empty and, in that case, I don't have a way to get the type of args. I could also use reflection to get the type, but since it's a generic function, I should also know this at compile-time.
Is there a way I can get name of T at compile time without having to print the type of any arguments or through reflection?
Printing the type name at compile time is not possible. Both fmt and reflect functions (which fmt uses) are run time operations. You might be able to find out the type of some expression with static analysis but again this is orthogonal to run-time printing.
Anyway at run time, if the type parameter list captures the base type of a composite type, including a vararg slice, you can simply print it by declaring a new variable of that type. The idiom *new(T) in particular allows to do it with one-liners:
func foo[T any](args ...T) string {
return fmt.Sprintf("%+v are of type %T", args, *new(T))
}
Calling that as foo(1,2,3) now gives the string:
"[1 2 3] are of type int"
Yes, the compiler is smart enough to know that *new(T) doesn't escape to the heap.
Is there a way I can get name of T at compile time without having to print the type of any arguments or through reflection?
No
You need reflection for this.

Passing pointer to string when the function takes an interface?

I am passing a pointer to a string, to a method which takes an interface (I have multiple versions of the method, with different receivers, so I am trying to work with empty interfaces, so that I don't end up with a ton of boilerplate madness. Essentially, I want to populate the string with the first value in the slice. I am able to see the value get populated inside the function, but then for some reason, in my application which calls it, tha value doesn't change. I suspect this is some kind of pointer arithmetic problem, but could really use some help!
I have the following interface :
type HeadInterface interface{
Head(interface{})
}
And then I have the following functions :
func Head(slice HeadInterface, result interface{}){
slice.Head(result)
}
func (slice StringSlice) Head(result interface{}){
result = reflect.ValueOf(slice[0])
fmt.Println(result)
}
and... here is my call to the function from an application which calls the mehtod...
func main(){
test := x.StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
x.Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println(result)
}
*NOTE : I am aware that getting the first element doesn't need to be this complicated, and could be slice[0] as a straight assertion, but this is more of an exercise in reusable code, and also in trying to get a grasp of pointers, so please don't point out that solution - I would get much more use out of a solution to my actual problem here * :)
As you said in your NOTE, I'm pretty sure this doesn't have to be this complicated, but to make it work in your context:
package main
import (
"fmt"
"reflect"
)
type HeadInterface interface {
Head(interface{})
}
func Head(slice HeadInterface, result interface{}) {
slice.Head(result)
}
type StringSlice []string
func (slice StringSlice) Head(result interface{}) {
switch result := result.(type) {
case *string:
*result = reflect.ValueOf(slice[0]).String()
fmt.Println("inside Head:", *result)
default:
panic("can't handle this type!")
}
}
func main() {
test := StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println("outside:", result)
}
The hard part about working with interface{} is that it's hard to be specific about a type's behavior given that interface{} is the most un-specific type. To modify a variable that you pass as a pointer to a function, you have to use the asterisk (dereference) (for example *result) on the variable in order to change the value it points to, not the pointer itself. But to use the asterisk, you have to know it's actually a pointer (something interface{} doesn't tell you) so that's why I used the type switch to be sure it's a pointer to a string.

Turning []interface{} into arguments to a non-variadic function

I am looking for an elegant way to unzip a list of arguments in Go. I do not want to use a variadic function for that purpose because in my usecase when writing a function I already know the number of arguments and I want to keep that part simple. However in my usecase the parameters arrive as []interface{}.
I could not find a solution but hey maybe someone out there already knows how to do that?
package main
import (
"fmt"
)
// NON-VARIADIC greater
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
// works
greet(l[0].(string), l[1].(string))
// does not work: "./args.go:20: not enough arguments in call to greet"
//greet(l...)
// is there something more elegant to unzip the list?
}
You could create a "generic" caller using reflect package, although this comes with overhead and lacks type safety. Unless you have some special case situation and don't know what you want to call in the code, it would be wiser to use the snippet from your question which works, but you consider not elegant.
Example usage of reflect which could be your starting point:
package main
import (
"fmt"
"reflect"
)
func call(f interface{}, args []interface{}) {
// Convert arguments to reflect.Value
vs := make([]reflect.Value, len(args))
for n := range args {
vs[n] = reflect.ValueOf(args[n])
}
// Call it. Note it panics if f is not callable or arguments don't match
reflect.ValueOf(f).Call(vs)
}
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
call(greet, l)
}
// Output: hello world
https://play.golang.org/p/vbi3CChCdV
I'm not quite sure what you're trying to do. If you want a way to easily pass a slice of two empty interfaces to a function that accepts two strings, you can create a little helper:
func twoStrings(vs []interface{}) (string, string) {
return vs[0].(string), vs[1].(string)
}
Use it as
greet(twoStrings(l))
Playground: http://play.golang.org/p/R8KFwMUT_V.
But honestly, it seems like you're doing something wrong, trying to make the Go type system to do something it cannot do.

The argument in golang RPC call

In the RPC handler function, I omit the first argument like:
func (self Handler) GetName(int, reply *StructObj) {
}
and in the calling side
var reply StructObj
client.Call("Handler.GetName", 0, &reply)
Because I do not need the first argument in the GetName Method, I omit its name,
HOWEVER, I got:
gob: type mismatch in decoder: want struct type
I changed the GetName method to GetName(id int, reply *StructObj) and it works.
I want to know why this happened?
You hit a tricky aspect of function definition syntax in Go. You can't have an unnamed argument, and you can name an argument int, and func f(x, y, z Type) is a shortcut to declare all three variables to be of type Type. For example, func f(int, x string) counterintuitively declares an f that accepts two strings, one of which happens to be named int.
package main
import "fmt"
func f(int, x string) {
fmt.Println("int is:", int)
fmt.Println("x is:", x)
}
func main() {
f("foo", "bar")
}
When you run it, the output is
int is: foo
x is: bar
Yes, that's a little mind-bending. I've never heard the specific thinking explained, but maybe they kept builtin type names un-reserved so they could later introduce new builtin types without breaking code that's already out there.
Anyway, it means your first function definition doesn't actually accept an int and a *StructObj but a *StructObj named int and another named reply. So the error message from net/rpc actually means that the client passed a 0 when it expected a *StructObj. Pretty fun.

Meaning of ...interface{} (dot dot dot interface)

Below is a piece of Go code I have question about.
Specifically, what is a in this function?
func DPrintf(format string, a ...interface{}) (n int, err error) {
if Debug > 0 {
n, err = fmt.Printf(format, a...)
}
return
}
Could anyone tell me what the three dots are here?
And what does ...interface{} do?
A parameter type prefixed with three dots (...) is called a variadic parameter. That means you can pass any number or arguments into that parameter (just like with fmt.Printf()). The function will receive the list of arguments for the parameter as a slice of the type declared for the parameter ([]interface{} in your case). The Go Specification states:
The final parameter in a function signature may have a type prefixed with .... A function with such a parameter is called variadic and may be invoked with zero or more arguments for that parameter.
A parameter:
a ...interface{}
Is, for the function equivalent to:
a []interface{}
The difference is how you pass the arguments to such a function. It is done either by giving each element of the slice separately, or as a single slice, in which case you will have to suffix the slice-value with the three dots. The following examples will result in the same call:
fmt.Println("First", "Second", "Third")
Will do the same as:
s := []interface{}{"First", "Second", "Third"}
fmt.Println(s...)
This is explained quite well in the Go Specification as well:
Given the function and calls
func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
within Greeting, who will have the value nil in the first call, and []string{"Joe", "Anna", "Eileen"} in the second.
If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.
Given the slice s and call
s := []string{"James", "Jasmine"}
Greeting("goodbye:", s...)
within Greeting, who will have the same value as s with the same underlying array.
As far as the interface{} term, it is the empty interface. In other words, the interface implemented by all variables in Go.
This is sort of analogous to java.lang.Object or System.Object in C#, but is instead inclusive of every variable type in the language. So it lets you pass in anything to the method.

Resources