What is the difference between *(*uintptr) and **(**uintptr) - function

In Go's runtime/proc.go, there is a piece of code showed below:
// funcPC returns the entry PC of the function f.
// It assumes that f is a func value. Otherwise the behavior is undefined.
// CAREFUL: In programs with plugins, funcPC can return different values
// for the same function (because there are actually multiple copies of
// the same function in the address space). To be safe, don't use the
// results of this function in any == expression. It is only safe to
// use the result as an address at which to start executing code.
//go:nosplit
func funcPC(f interface{}) uintptr {
return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
}
What I don't understand is why not use *(*uintptr) instead of **(**uintptr)?
So I write a test program below to figure out.
package main
import (
"fmt"
"unsafe"
)
func main(){
fmt.Println()
p := funcPC(test)
fmt.Println(p)
p1 := funcPC1(test)
fmt.Println(p1)
p2 := funcPC(test)
fmt.Println(p2)
}
func test(){
fmt.Println("hello")
}
func funcPC(f func()) uintptr {
return **(**uintptr)(unsafe.Pointer(&f))
}
func funcPC1(f func()) uintptr {
return *(*uintptr)(unsafe.Pointer(&f))
}
The result that p doesn't equal p1 makes me confused.
Why doesn't the value of p equal the value of p1 while their type is the same?

Introduction
A function value in Go denotes the funtion's code. From far, it is a pointer to the function's code. It acts like a pointer.
From a closer look, it's a struct something like this (taken from runtime/runtime2.go):
type funcval struct {
fn uintptr
// variable-size, fn-specific data here
}
So a function value holds a pointer to the function's code as its first field which we can dereference to get to the function's code.
Explaining your example
To get the address of a function('s code), you may use reflection:
fmt.Println("test() address:", reflect.ValueOf(test).Pointer())
To verify we get the right address, we may use runtime.FuncForPC().
This gives the same value as your funcPC() function. See this example:
fmt.Println("reflection test() address:", reflect.ValueOf(test).Pointer())
fmt.Println("funcPC(test):", funcPC(test))
fmt.Println("funcPC1(test):", funcPC1(test))
fmt.Println("func name for reflect ptr:",
runtime.FuncForPC(reflect.ValueOf(test).Pointer()).Name())
It outputs (try it on the Go Playground):
reflection test() address: 919136
funcPC(test): 919136
funcPC1(test): 1357256
func name for reflect ptr: main.test
Why? Because a function value itself is a pointer (it just has a different type than a pointer, but the value it stores is a pointer) that needs to be dereferenced to get the code address.
So what you would need to get this to uintptr (code address) inside funcPC() would be simply:
func funcPC(f func()) uintptr {
return *(*uintptr)(f) // Compiler error!
}
Of course it doesn't compile, conversion rules do not allow converting a function value to *uintptr.
Another attempt may be to convert it first to unsafe.Pointer, and then to *uintptr:
func funcPC(f func()) uintptr {
return *(*uintptr)(unsafe.Pointer(f)) // Compiler error!
}
Again: conversion rules do not allow converting function values to unsafe.Pointer. Any pointer type and uintptr values may be converted to unsafe.Pointer and vice versa, but not function values.
That's why we have to have a pointer value to start with. And what pointer value could we have? Yes, the address of f: &f. But this will not be the function value, this is the address of the f parameter (local variable). So &f schematically is not (just) a pointer, it's a pointer to pointer (that both need to be dereferenced). We can still convert it to unsafe.Pointer (because any pointer value qualifies for that), but it's not the function value (as a pointer), but a pointer to it.
And we need the code address from the function value, so we have to use **uintptr to convert the unsafe.Pointer value, and we have to use 2 dereferences to get the address (and not just the pointer in f).
This is exactly why funcPC1() gives a different, unexpected, incorrect result:
func funcPC1(f func()) uintptr {
return *(*uintptr)(unsafe.Pointer(&f))
}
It returns the pointer in f, not the actual code address.

It returns a different value because **(**uintptr) is not the same as *(*uintptr). The former is a double indirection, the later a simple indirection.
In the former case, the value is a pointer to a pointer to a pointer to a uint.

Related

Can I create an alias for a generic function? I get error "Cannot use generic function without instantiation"

I can define a generic function:
package hello
func IsZero[T int64|float64](value T) bool {
return value == 0
}
Then if I try to alias that function in another package, it fails:
package world
import "hello"
var IsZero = hello.IsZero
The above doesn't compile with:
cannot use generic function hello.IsZero without instantiation
Instead this works:
var IsZero = hello.IsZero[int64]
Is it possible to do this, using some other syntax?
That's not an alias. And you already have your answer, actually. But if you want a formal reference, from the language specs, Instantiations:
A generic function that is is not called requires a type argument list for instantiation
So when you attempt to initialize a variable of function type, the function hello.IsZero is not called, and therefore requires instantiation with specific type parameters:
// not called, instantiated with int64
var IsZero = hello.IsZero[int64]
At this point the variable (let's give it a different name for clarity) zeroFunc has a concrete function type:
var zeroFunc = IsZero[int64]
fmt.Printf("type: %T\n", zeroFunc)
Prints:
type: func(int64) bool
This might or might not be what you want, as this effectively monomorphises the function.
If you just want to have a local symbol, with the same implementation (or a tweaked version thereof), declaring a "wrapper" function works. Just remember that the type parameters of your wrapper can only be as strict or stricter than the wrapped one's
E.g. Given
IsZero[T int64 | float64](v T)
your wrapper can not be
WrapIsZeroPermissive[T int64 | float64 | complex128](v T) bool {
return IsZero(v) // does not compile, T's type set is a superset
}
but can be
WrapIsZeroStricter[T int64](v T) bool {
return IsZero(v) // ok, T's type set is a subset
}
If the function is small, like in the question, it's probably easier to just vendor it:
package vendor
func thisIsJustCopy[T int64|float64](value T) bool {
return value == 0
}
but if the function is big, you can do it like this:
package world
import "hello"
func IsZero[T int64|float64](value T) bool {
return hello.IsZero(value)
}
I try to alias that function in another package
Aliases work for types only. Your code just tries to declare a variable.
Is it possible to do this, using some other syntax?
No.

Overloading a function in go doesn't work

I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)

C++11: Why result_of can accept functor type as lvalue_reference, but not function type as lvalue_reference?

I've got program below:
#include<type_traits>
#include<iostream>
using namespace std;
template <class F, class R = typename result_of<F()>::type>
R call(F& f) { return f(); }
struct S {
double operator()(){return 0.0;}
};
int f(){return 1;}
int main()
{
S obj;
call(obj);//ok
call(f);//error!
return 0;
}
It fails to compile in the line of "call(f)".
It's weird that "call(obj)" is OK.
(1) I've a similar post in another thread C++11 result_of deducing my function type failed. But it doesn't tell why functor objects are OK while functions are not.
(2) I'm not sure if this is related to "R call(F& f)": a function type cannot declare a l-value?
(3) As long as I know, any token with a name, like variable/function, should be considered a l-value. And in the case of function parameter, compiler should "decay" my function name "f" to a function pointer, right?
(4) This is like decaying an array and pass it to a function----And a function pointer could be an l-value, then what's wrong with "call(F& f)"?
Would you help to give some further explanations on "why" is my case, where did I get wrong?
Thanks.
The problem with call(f) is that you deduce F as a function type, so it doesn't decay to a function pointer. Instead you get a reference to a function. Then the result_of<F()> expression is invalid, because F() is int()() i.e. a function that returns a function, which is not a valid type in C++ (functions can return pointers to functions, or references to functions, but not functions).
It will work if you use result_of<F&()> which is more accurate anyway, because that's how you're calling the callable object. Inside call(F& f) you do f() and in that context f is an lvalue, so you should ask what the result of invoking an lvalue F with no arguments is, otherwise you could get the wrong answer. Consider:
struct S {
double operator()()& {return 0.0;}
void operator()()&& { }
};
Now result_of<F()>::type is void, which is not the answer you want.
If you use result_of<F&()> then you get the right answer, and it also works when F is a function type, so call(f) works too.
(3) As long as I know, any token with a name, like variable/function, should be considered a l-value. And in the case of function parameter, compiler should "decay" my function name "f" to a function pointer, right?
No, see above. Your call(F&) function takes its argument by reference, so there is no decay.
(4) This is like decaying an array and pass it to a function----And a function pointer could be an l-value, then what's wrong with "call(F& f)"?
Arrays don't decay when you pass them by reference either.
If you want the argument to decay then you should write call(F f) not call(F& f). But even if you do that you still need to use result_of correctly to get the result of f() where f is an lvalue.

Empty interface{} in function type

An object of any type can be assigned to an empty interface. For example, we have the following function
func Println(i interface{} ) {
fmt.Println(i)
}
We can call it by
Println(3)
Println(1.5)
Println("Hello")
But I can't achieve the same thing for function type
func Map(fn func( interface{} )) {
......
}
I cannot call this with
Map( func( i int) {......} )
because the type func(int) is different from the type func( interface{} ).
But when I define func( interface{} ), I really mean any type of the input parameters. How can I achieve this in Go?
It fails because the signatures don't match.
When you call Println(3), the function isn't taking an integer as its first argument. Rather the integer gets packed inside an interface{} variable (an automatic conversion, since integers conform to the interface), and that variable is passed to the function. This conversion happens on the calling side, so the process of calling the function is different to calling a function matching func(i int).
If you want to write a function that accepts arbitrary unary functions, you will need to declare it to take an interface{} variable as its argument and then check the value using the reflect package. The reflect package can also help you call arbitrary functions where you don't know the signature at compile time.
For example:
func Map(f, v interface{}) interface{} {
fn := reflect.ValueOf(f)
fnType := fn.Type()
if fnType.Kind() != reflect.Func || fnType.NumIn() != 1 || fnType.NumOut() != 1 {
panic("Expected a unary function returning a single value")
}
res := fn.Call([]reflect.Value{reflect.ValueOf(v)})
return res[0].Interface()
}
This will call the given function f with the argument v and return the result. Provided v is assignable to f's first argument the call will succeed without a panic. You can experiment with this example here: http://play.golang.org/p/kkBu56JYb8
I do realise its an old discussion, but came across the post and wanted to play around with the concept of having arbitrary function func (interface{}) within another function, instead of interface{}.
I could write a simple implementation, by providing an inline implementation of a function which would accept interface{}. And we can call this function from within another function
varForGenFunc := func(in interface{}) int {
fmt.Println("type of this object: ",reflect.TypeOf(in))
return 1}
TakeGenericFunc(varForGenFunc, variableForGen)
Going by this, we can write any implementations of func(interface{}) and pass it as parameter to TakeGenericFunc
You can play around with it here:
https://play.golang.org/p/f5UUhyhEx7u

How does this Go function type "HandlerFunc" work, from the standard library "net/http"

I'm confused about this bit of code from the HTTP package:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
Why does the ServeHTTP method have the exact same signature as it's type - what's the point?
Testing, I discovered that if I pass a random function (foo) to the HandlerFunc:
var bar = HandlerFunc(foo)
bar becomes an instance of HandlerFunc with foo as its ServeHTTP method. Now I'm really confused about how on earth this works.
If I have more than one methods on a type, how do I know which one is going to be attached to the new instance and with what name or order?
This approach allows you to use a function in a context that's expecting a Handler.
What happens is, there's a Handler interface:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
and various functions are declared to accept parameters that are declared to belong to this interface — for example:
func TimeoutHandler(h Handler, ns int64, msg string) Handler {
f := func() <-chan int64 {
return time.After(ns)
}
return &timeoutHandler{h, f, msg}
}
What this means is that when you invoke such a function, you have to pass in an object belonging to a type that satisfies this interface, which is to say, a type that has a ServeHTTP method with the appropriate signature. (In Go, unlike some languages, a type doesn't need to explicitly implement an interface, it just needs to have the methods specified by the interface.)
So, the code-snippet that you quote:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
creates a type HandlerFunc that's based on func(ResponseWriter, *Request), but augments the type with a method called ServeHTTP with an appropriate signature, so that it satisfies the Handler interface. This ServeHTTP method just calls the function itself. So, if f is a function with the right signature, you could write something like this:
var h HandlerFunc = f // h == f, but converted to a HandlerFunc
// so it satisfies the Handler interface.
TimeoutHandler(h, 1000000, "timed out")
To clarify a few things about this:
Testing, I discovered that if I pass a random function (foo) to the HandlerFunc:
var bar = HandlerFunc(foo)
bar becomes an instance of HandlerFunc with foo as its ServeHTTP method. Now I'm really confused about how on earth this works.
Firstly, it's more correct to say that you've converted a random function foo to type HandlerFunc, rather than that you've passed the function to HandlerFunc as though HandlerFunc were a function. (The HandlerFunc(foo) notation is a typecast; you could just as well write var bar HandlerFunc = foo and let the conversion happen implicitly.)
Secondly, it's more correct to say that bar has a ServeHTTP method that invokes foo, than that foo itself actually is the ServeHTTP method.
Does that make sense?