golang has pointer's pointer or pointer's reference feature? - pointers

Hi everyone in Golang what will you do if you need to change the pointer (change where the pointer points to rather than change the value where this pointer points to). I know it is really easy in C++ by using reference, like"
void myFunc(Type*& ptr)
{
ptr = anotherPointer;
}
int main
{
Type* ptr = &someValue;
myFunc(ptr); // ptr is moved
}
Or equivalently in C, use pointer's pointer:
void myFunc(Type** ptrsptr)
{
*ptrsptr = anotherPointer;
}
int main
{
Type* ptr = &someValue;
myFunc(&ptr); // ptr is moved
}
I wonder if Golang has this neat feature, or if not, the only way is to set at function's return?

You can use a pointer to a pointer, just like in C
http://play.golang.org/p/vE-3otpKkb
package main
import "fmt"
type Type struct{}
var anotherPointer = &Type{}
func myFunc(ptrsptr **Type) {
*ptrsptr = anotherPointer
}
func main() {
ptr := &Type{}
fmt.Printf("%p\n", ptr)
myFunc(&ptr) // ptr is moved
fmt.Printf("%p\n", ptr)
}

The below example will change the value of variable only:
package main
import "fmt"
func main() {
value := 200
var p1 *int = &value
var p2 **int = &p1
fmt.Printf("Value of variable before updating %v and address of pointer is: %p\n", *p1, p1)
*p1 = 300
fmt.Printf("Value of variable after updating by p1 %v and address of pointer is: %p\n", *p1, p1)
**p2 = 400
fmt.Printf("Value of variable after updating by p2 %v and address of pointer is: %p\n", *p1, p1)
}
The below code will change the pointer value and also point to new address:
package main
import "fmt"
func changePointer(newP **int) {
val := 500
*newP = &val
}
func main() {
value := 200
var p1 *int = &value
fmt.Printf("Value of variable before updating %v and address of pointer is: %p\n", *p1, p1)
changePointer(&p1)
fmt.Printf("Value of variable after updating %v and address of pointer is: %p\n", *p1, p1)
}

Related

C struct is nil when return in Go

I am trying to create a C struct point and pass it to Go but I keep getting a nil pointer. I have the following in C and calling from Go.
test.h
#include <stdio.h>
typedef struct TestStruct {
int test_int;
} TestStruct;
TestStruct* newTestStruct();
test.c
TestStruct* newTestStruct() {
printf("[C] Creating TestStruct...\n");
TestStruct test = {0};
test.test_int = 10;
TestStruct* testPtr = &test;
if (testPtr == NULL) {
printf("[C] TestStruct is NULL.\n");
}
fflush(stdout);
return testPtr;
}
test.go
package teststruct
import "log"
// #include "test.h"
import "C"
type TestStruct C.struct_TestStruct
func NewTestStruct() *TestStruct {
t := C.newTestStruct()
if t == nil {
log.Errorf("[Go] TestStruct is nil.")
}
return (*TestStruct)(t)
}
It prints off the following:
[C] Creating TestStruct...
[Go] TestStruct is nil.
Why is this nil on the Go side?
You are returning a pointer to a stack-allocated structure in C, which is very wrong.
The pointer returned from newTestStruct is essentially dangling and trying to access any data through it may lead to crashes or worse.
Make sure to allocate data on the heap if you want to return a pointer to it, something like:
TestStruct* newTestStruct() {
printf("[C] Creating TestStruct...\n");
TestStruct* testPtr = (TestStruct*)malloc(sizeof(TestStruct));
testPtr->test_int = 10;
if (testPtr == NULL) {
printf("[C] TestStruct is NULL.\n");
}
fflush(stdout);
return testPtr;
}
By the way, on any half-modern C compiler you'd get a warning for your C code, something like warning: function returns address of local variable [-Wreturn-local-addr]

Set pointer to nil via function

There is a function that sets a pointer to a nil value:
func nilSetter(x *int) {
x = nil
}
I have such snippet of code:
i := 42
fmt.Println(&i)
nilSetter(&i)
fmt.Println(&i)
Which prints:
0xc42008a000
0xc42008a000
While I expect:
0xc42008a000
nil
I know that it happens because function nilSetter just copy address and sets to nil that copy.
But how can I do it correctly?
The only way to achieve that is with a pointer to a pointer. And it's pretty clunky so it's probably not what you want:
func nilSetter(x **int) {
*x = nil
}
func main() {
x := 2
xp := &x
fmt.Println(xp)
nilSetter(&xp)
fmt.Println(xp)
}
// Output:
// 0x10414020
// <nil>
The reason of such behaviour is because there is no pass by reference in Go.
Two variables can have contents that point to the same storage location. But, it is not possible to have them share the same storage location.
Example:
package main
import "fmt"
func main() {
var a int
var b, c = &a, &a
fmt.Println(b, c) // 0x1040a124 0x1040a124
fmt.Println(&b, &c) // 0x1040c108 0x1040c110
}
From your code, the argument x of nilSetter is pointing to some location but it have its own address and when you are setting a nil to it, you are changing its address not the address of what it is pointing to.
package main
import "fmt"
func nilSetter(x *int) {
x = nil
fmt.Println(x, &x) // <nil> 0x1040c140
}
func main() {
i := 42
fmt.Println(&i) // 0x10414020
nilSetter(&i)
fmt.Println(&i) // 0x10414020
}
That is why pointers always have an exact address even its value is nil
Referencing to a blog post by Dave Cheney: https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Just use return value and assign.
func nilSetter(x *int) *int {
x = nil
return x
}
x = nilSetter(x)

Golang create struct in different way

guys! I am a beginner in Go. I have some doubts When I learning reflect package ,here's the code:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func checkError(err error) {
if err != nil {
panic(err)
}
}
type Test struct {
X int
Y string
}
func main() {
fmt.Println("hello world!")
test1()
test2()
}
func test1() {
a := Test{}
fmt.Printf("a: %v %T \n", a, a)
fmt.Println(a)
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
checkError(err)
fmt.Printf("a: %v %T \n", a, a)
}
func test2() {
fmt.Println("===========================")
m := make(map[string]reflect.Type)
m["test"] = reflect.TypeOf(Test{})
a := reflect.New(m["test"]).Elem().Interface()
fmt.Printf("a: %v %T \n", a, a)
fmt.Println(a)
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
checkError(err)
fmt.Printf("a: %v %T \n", a, a)
}
and the result :
a: {0 } main.Test
{0 }
a: {1 x} main.Test
===========================
a: {0 } main.Test
{0 }
a: map[X:1 Y:x] map[string]interface {}
Why these two way make different result, Could anyone tell me why, many thanks.
In test2 you're passing in the address of the interface{} containing a Test value. When the value is dereferenced by the json package it only sees an interface{}, and therefor it unmarshals into the default types.
What you need is an interface{} containing a pointer to a Test value.
// reflect.New is creating a *Test{} value.
// You don't want to dereference that with Elem()
a := reflect.New(m["test"]).Interface()
// 'a' contains a *Test value. You already have a pointer, and you
// don't want the address of the interface value.
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), a)

How to define a pointer in go, then pass this pointer in to a func to change its value?

import "fmt"
func zeroptr(ptr *int) {
*ptr = 0
}
func main() {
oneptr * int
*ptr = 1
fmt.Println("ptr is :", *ptr)
zeroptr(ptr)
fmt.Println("after calling zeroptr, the value of ptr is :", *ptr)
}
This does not work, I am looking for output as follows:
ptr is :1
after calling zeroptr, the value of ptr is : 0
You should use pass an &int to zeroptr, as in this example:
package main
import "fmt"
func zeroptr(ptr *int) {
*ptr = 0
}
func main() {
var ptr int
ptr = 1
fmt.Println("ptr is :", ptr)
zeroptr(&ptr)
fmt.Println("after calling zeroptr, the value of ptr is :", ptr)
}
Output:
ptr is : 1
after calling zeroptr, the value of ptr is : 0
You can see a similar example in "What's the point of having pointers in Go?", from the golang book.
What does your pointer point to? In order to manipulate the memory a pointer points to, you first need to point the pointer somewhere. Right now, your ptr is pointing to nil which is invalid. You could for instance do this:
func main() {
var foo int
var oneptr *int = &foo
*oneptr = 1
fmt.Println("oneptr is :", *oneptr)
zeroptr(oneptr)
fmt.Println("after calling zeroptr, the value of oneptr is :", *ptr)
}
For the future, please indent your code before submitting it here. You can do this with the gofmt program.

Point to Struct in Golang

I has encountered an error while implement the below code:
package main
import (
"fmt"
)
type Struct struct {
a int
b int
}
func Modifier(ptr *Struct, ptrInt *int) int {
*ptr.a++
*ptr.b++
*ptrInt++
return *ptr.a + *ptr.b + *ptrInt
}
func main() {
structure := new(Struct)
i := 0
fmt.Println(Modifier(structure, &i))
}
That gives me an error something about "invalid indirect of ptr.a (type int)...". And also why the compiler don't give me error about ptrInt? Thanks in advance.
Just do
func Modifier(ptr *Struct, ptrInt *int) int {
ptr.a++
ptr.b++
*ptrInt++
return ptr.a + ptr.b + *ptrInt
}
You were in fact trying to apply ++ on *(ptr.a) and ptr.a is an int, not a pointer to an int.
You could have used (*ptr).a++ but this is not needed as Go automatically solves ptr.a if ptr is a pointer, that's why you don't have -> in Go.

Resources