Is it possible in Go to pass pointer of string and make it slice of string? - pointers

So basically I was wondering if it possible in GO, because I was playing with Dereference.
For example in Code shown below. Pointer is passed to function and I'm trying to return one letter of passed pointer string, in given example that is H, but however slice can only be used with strings. And I was wondering if it possible to do this using pointer Dereference.
Code Example:
func Test(test *string) {
if len(*test) > 0 {
*test = *test[:1]
}
strings.ToUpper(*test)
}
func main() {
str := "hello"
Test(&str)
fmt.Print( str)
}

Is it possible in Go to pass pointer of string and make it slice of string?
Yes: func (ps *string) []string { return []string{*ps} }

You need to place test in brackets, i.e. dereference the pointer first, and then slice it.
Then the Test function still wouldn't return capital H though, because ToUpper takes and returns a value. So you need to reassign the output of ToUpper to *test as well:
func Test(test *string) {
if len(*test) > 0 {
*test = (*test)[:1] // bracketed `test`
}
*test = strings.ToUpper(*test) // reassign to `test`
}
func main() {
str := "hello"
Test(&str)
fmt.Print(str) // Prints 'H'
}
Go Play example

Related

Why is a pointer to a Go bytes.Buffer required when passing it to another function?

In the code below, write_commas requires the buffer parameter to be a pointer. It works.
The alternative (ie. NOT using a pointer) results in blank output.
Why is it that passing the actual bytes.Buffer fails to print anything? Or put another way, does passing the actual bytes.Buffer create a copy and thus, the bytes get written to a buffer that nothing is reading?
package main
import (
"fmt"
"bytes"
)
func main() {
s := "1234567898"
fmt.Println(Comma(s))
}
func Comma(s string) string {
var buf bytes.Buffer // <-- bytes.Buffer declared here.
sbytes := []byte(s)
decimal := bytes.LastIndex(sbytes,[]byte("."))
if decimal > 0 {
whole_part := sbytes[:decimal]
write_commas(whole_part, &buf) // <-- Address
float_part := sbytes[decimal:len(sbytes)]
for i := len(float_part); i > 0; i-- {
buf.WriteByte(float_part[len(float_part)-i])
}
} else {.
write_commas(sbytes, &buf) // <-- Address
}
return buf.String()
}
func write_commas(byr []byte, buf *bytes.Buffer) { // <-- Why *bytes.Buffer?
for i := len(byr); i > 0; i-- {
buf.WriteByte(byte(byr[len(byr)-i]))
if i > 1 && (i-1) % 3 == 0 {
buf.WriteByte(',')
}
}
}
Any time you pass an argument to a function, it creates a local copy within that function. When you pass a pointer, the function receives a copy of the pointer, which points to the same underlying value. So, if you pass a pointer, the function can affect the value it points to, which the caller will then see. If you pass a copy of the value instead (instead of passing a pointer), the function is manipulating the copy, which has no effect on the caller's own copy.

Go slice pointer in variable changes behaviour during append

I'm a bit confused as to why this happens when attempting to remove an element from a slice in Go.
As a simplified example, I have the following data structures:
type Person struct {
Name string
}
type People []Person
I want to add a method to remove a person with a certain name from the list of people with people.Remove("Sam"):
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Doesn't work
*p = append(*p[:i], *p[i+1:]...)
}
}
}
I thought this would work, but referencing the slice elements in this manner returns a compile error: cannot slice p (type *People).
So, fair enough. But when I set *p to another variable (a), it works exactly as expected:
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Does work
a := *p
*p = append(a[:i], a[i+1:]...)
}
}
}
Why do I need to set the slice to a difference variable before this method works? Shouldn't the behaviour be exactly the same?
I'm probably misunderstanding something fundamental here so if anyone can explain why this is required I'd love to know. Thank you!
The slice expressions in *p = append(*p[:i], *p[i+1:]...) take precedence over the * operator. You need to enclose those in parentheses.
func (p *People) Remove(name string) {
for i, person := range *p {
if person.Name == name {
// Doesn't work
*p = append((*p)[:i], (*p)[i+1:]...)
}
}
}
https://play.golang.org/p/cbT65mCzA4h

What is the difference between passing a struct and pointer of the struct, are they not both pointers?

For example
var myStructRef *Vertex
var myStruct Vertex
myStructRef = &Vertex{2, 3}
myStruct = Vertex{2, 3}
fmt.Println(myStructRef)
fmt.Println(myStruct)
changeByReferenceStruct(myStructRef)
changeByValueStruct(myStruct)
fmt.Println(myStructRef)
fmt.Println(myStruct)
And
func changeByValueStruct(myStruct Vertex) {
myStruct.X = 5
fmt.Println(myStruct)
}
func changeByReferenceStruct(myStruct *Vertex) {
myStruct.X = 7
fmt.Println(myStruct)
}
Isn't both myStructRef *Vertex and myStruct Vertex a pointer pointing to the struct itself? Why is there a discrepancy in behavior when I modify the struct in a function?
Is golang creating a new struct in changeByValueStruct when it resolves the parameter?
When you pass a pointer as an argument, what happens under the hood is that a copy of that pointer is created and passed to the underlying function. It should not be confused with pass-by-reference.
Let's look at an example to better grasp it:
package main
import (
"fmt"
)
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func modifyValue(point Point) {
point.x += 10
}
func modifyPointer(point *Point) {
point.x = 5
point.y = 5
}
func modifyReference(point *Point) {
point = &Point{5, 5}
}
func main() {
p := Point{0, 0}
fmt.Println(p) // prints (0, 0)
modifyValue(p)
fmt.Println(p) // prints (0, 0)
modifyPointer(&p)
fmt.Println(p) // prints (5, 5)
p = Point{0, 0}
modifyReference(&p)
fmt.Println(p) // prints (0, 0)
}
What happens inside the modifyValue function is that a totally different instance of a Point structure is modified, so the value passed when calling the function is unaffected.
In the second example, a pointer to the structure is passed so the fields of the structure can be modified in a way that is visible from outside.
The most interesting point is made by the last function, modifyReference. If you are familiar with the pass by reference paradigm available in other languages you would expect to be able to modify the referenced object altogether, but this doesn't happen. It's because you're modifying a copy of the pointer passed as argument.
You may wonder, if everything is passed by value, when should you pass pointers and when values. Passing values assures the caller function that the passed structure cannot suffer any changes, so when you need this behaviour, go for the value. The downside of this is that a copy of the entire object is made and, if it is too big, memory becomes a concern.
If you're passing a big structure as an argument, using a pointer is better because it saves space, but you lose the guarantee that the object won't suffer any changes.
Passing struct to function argument makes copy of values. And passing pointer of struct doesn't. So passing struct can't update field value.
package main
import (
"fmt"
)
type Foo struct {
value int
}
func PassStruct(foo Foo) {
foo.value = 1
}
func PassStructPointer(foo *Foo) {
foo.value = 1
}
func main() {
var foo Foo
fmt.Printf("before PassStruct: %v\n", foo.value)
PassStruct(foo)
fmt.Printf("after PassStruct: %v\n", foo.value)
fmt.Printf("before PassStructPointer: %v\n", foo.value)
PassStructPointer(&foo)
fmt.Printf("after PassStructPointer: %v\n", foo.value)
}
https://play.golang.org/p/AM__JwyaJa

How to get the address of a function in go?

Is it possible to get the address of a function reference in Go?
Something like
func myFunction() {
}
// ...
unsafe.Pointer(&myFunction)
Just that is does not work that way. My guess it's not possible, but I did not found any proof yet.
Edit: Background
The background of my question comes from dealing with CGO and C Function pointers.
This works:
/*
void go_myFunction();
typedef void (*myFunction_f)();
myFunction_f pMyFunction;
*/
import "C"
//export go_myFunction
func go_myFunction() {
// ...
}
func SetupFp() {
C.pMyFunction = (*[0]byte)(unsafe.Pointer(C.go_myFunction))
}
I'm also aware that the documentation states that passing a pointer to a go function does not work. But the above code seems no to be that far from it. I was just wondering if one could somehow skip the export step.
function type in Go is not addressable and not comparable because:
Function pointers denote the code of the function. And the code of an anonymous function created by function literal is only stored once in memory, no matter how many times the code that returns the anonymous function value runs.
Original answer
If you need to compare addresses of a functions you can do it with reflect.Pointer. But any way this operation is more senseless than impossible because:
If v's Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value.
You may get the address of a Go function like this:
package main
import (
"fmt"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func main() {
var ptr uintptr = reflect.ValueOf(HelloWorld).Pointer()
fmt.Printf("0x%x", ptr)
}
You can get address of function use function GetFuncAddr:
package main
import (
"fmt"
"unsafe"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func GetFuncAddr(i interface{}) uintptr {
type IHeader struct {
typ uintptr
word uintptr
}
return (*IHeader)(unsafe.Pointer(&i)).word
}
func main() {
tmp := HelloWorld
ptr1 := *(*uintptr)(unsafe.Pointer(&tmp)) //Way 1
ptr2 := GetFuncAddr(HelloWorld) //Way 2
fmt.Printf("0x%x = 0x%x", ptr1, ptr2)
//Thits is not are functon addrress!!!
BadPTR1 := reflect.ValueOf(HelloWorld).Pointer()
BadPTR2 := **(**uintptr)(unsafe.Pointer(&tmp)) //dereferenced pointer
fmt.Printf("\nBAD: 0x%x = 0x%x", BadPTR1 , BadPTR2 )
}

Ignore trailing return value in GO like in map[key] [duplicate]

In Go, the following works (note one use of the map has one return, the other has two returns)
package main
import "fmt"
var someMap = map[string]string { "some key": "hello" }
func main() {
if value, ok := someMap["some key"]; ok {
fmt.Println(value)
}
value := someMap["some key"]
fmt.Println(value)
}
However, I have no idea how to do this same thing with my own function. Is it possible to have similar behavior with an optional return like map?
For example:
package main
import "fmt"
func Hello() (string, bool) {
return "hello", true
}
func main() {
if value, ok := Hello(); ok {
fmt.Println(value)
}
value := Hello()
fmt.Println(value)
}
Wont compile (due to the error multiple-value Hello() in single-value context) ... is there a way to make this syntax work for the function Hello()?
map is different because it is a built-in type and not a function. The 2 forms of accessing an element of a map is specified by the Go Language Specification: Index Expressions and backed by the compiler.
With functions you can't do this. If a function has 2 return values, you have to "expect" both of them or none at all.
However you are allowed to assign any of the return values to the Blank identifier:
s, b := Hello() // Storing both of the return values
s2, _ := Hello() // Storing only the first
_, b3 := Hello() // Storing only the second
You can also choose not to store any of the return values:
Hello() // Just executing it, but storing none of the return values
Note: you could also assign both of the return values to the blank identifier, although it has no use (other than validating that it has exactly 2 return values):
_, _ = Hello() // Storing none of the return values; note the = instead of :=
You can also try these on the Go Playground.
Helper function
If you use it many times and you don't want to use the blank identifier, create a helper function which discards the 2nd return value:
func Hello2() string {
s, _ := Hello()
return s
}
And now you can do:
value := Hello2()
fmt.Println(value)
Go 1.18 generics update: Go 1.18 adds generics support, it is now possible to write a generic First() function which discards the second (or any further) return values:
func First[T any](first T, _ ...any) T {
return first
}
This is available in github.com/icza/gog, as gog.First() (disclosure: I'm the author).
Using it:
value := First(Hello())
fmt.Println(value)
In addition to the explanation of #icza:
I don't recommend using a helper function there. Especially if the Hello function is your own function.
However, if you can't control it, then it's fine to use a helper.
If it's your own function, it's better to change the signature of your function. Probably, you made a design mistake somewhere.
You can also do this:
package main
import "fmt"
func Hello() (string, bool) {
return "hello", true
}
func main() {
// Just move it one line above: don't use a short-if
value, ok := Hello()
if ok {
fmt.Println(value)
}
}

Resources