BigInt pointer in Go - pointers

I was playing around with various packages and data types and I came across this function(big.NewInt()) from "math/big" package. so this function returns a pointer to the type bigInt but when i print it out i get the actual value not the address where it is stored can anyone help me understand this better?
package main
import "fmt"
import "math/big"
import "reflect"
func main(){
target := big.NewInt(1)
a := 5
s := &a
fmt.Println(reflect.TypeOf(target))
fmt.Println(reflect.TypeOf(s))
fmt.Println(s)
fmt.Println(target)
}

fmt.Printf("%p\n", target) // 0xc00000c080

Related

Golang : convert Byte slice array to integer array

In Golang, the code [body, err := ioutil.ReadAll(resp.Body)], the ioutil.ReadAll() returns a byte Slice array, based on the documentation.
This is stored in the variable 'body'. My question is how to convert this byte Slice array, to an array of Integers.
I just found some code that does what I was wanting:
import "fmt"
import "strconv"
func main() {
var t = []string{"1", "2", "3"}
var t2 = []int{}
for _, i := range t {
j, err := strconv.Atoi(i)
if err != nil {
panic(err)
}
t2 = append(t2, j)
}
fmt.Println(t2)
}
So this code, does do what I want.
BUT l am disappointed in Golang, for not having a nice one liner that could do this
kind of conversion.
Certain basic things like this, should be packaged up for the programmer, and not have to do this kind of 'low' level programming.
Note, i still like Golang, they had done a lot to make a better C type language that has higher level Data Types when compared to C and also make some things more dynamic compared to C.
SO just disappointed they did not make a High Abstraction for this kind of case, which comes up quite a bit.

What's the difference between struct pointer and integer pointer output?

package main
import "fmt"
type Employee struct {
ID int
Name string
}
func main(){
var zhexiao Employee
zhexiao.Name = "xiao"
fmt.Println(&zhexiao)
x := 1
p := &x
fmt.Println(p)
}
The above code outputs two kinds of pointers.
struct pointer output is: &{0 xiao}
integer pointer output is: 0xc0420600b0 (it looks like a memory address)
Why struct pointer output is not a memory address? If it's not memory address, what is it?
Thanks a lot
Zhe
It depends on how you look at it. You are implicitly using the package fmt default print verb (%v). Here are some other ways to look at it by explicitly using other print verbs.
package main
import "fmt"
type Employee struct {
ID int
Name string
}
func main() {
var zhexiao Employee
zhexiao.Name = "xiao"
fmt.Printf("%[1]v %[1]p\n", &zhexiao)
x := 1
fmt.Printf("%[1]v %[2]p\n", x, &x)
p := &x
fmt.Printf("%[1]v %[1]p\n", p)
}
Playground: https://play.golang.org/p/4dV8HtiS8rP
Output:
&{0 xiao} 0x1040a0d0
1 0x1041402c
0x1041402c 0x1041402c
Reference: Package fmt: Printing

Accessing a Memory Address From a String in Go?

In golang, can I print the value of a memory address from a given string?
For example, if run the following code:
a := "A String"
fmt.Println(&a)
It prints 0x1040c108.
How could I take a string such as 0x1040c108 and print the value of that string stored in the memory? Something like fmt.Println(*0x1040c108)
Is this possible?
This can be done, but it is a really really REALLY bad idea. Anytime you are importing the unsafe package, you are either doing something wrong, or something really hardcore. I'm hesitant to even answer this, but here goes.
https://play.golang.org/p/unkb-s8IzAo
package main
import (
"fmt"
"strconv"
"unsafe"
)
func main() {
// original example manually examined the printed address and used the value
// updated to preserve forward compatibility due to runtime changes shifting the address over time
hi := "HI"
// getting address as string dynamically to preserve compatibility
address := fmt.Sprint(&hi)
fmt.Printf("Address of var hi: %s\n", address)
// convert to uintptr
var adr uint64
adr, err := strconv.ParseUint(address, 0, 64)
if err != nil {
panic(err)
}
var ptr uintptr = uintptr(adr)
fmt.Printf("String at address: %s\n", address)
fmt.Printf("Value: %s\n", ptrToString(ptr))
}
func ptrToString(ptr uintptr) string {
p := unsafe.Pointer(ptr)
return *(*string)(p)
}
And yes, this was pretty much taken almost line for line from the unsafe godoc. https://godoc.org/unsafe
Also note that if/when your memory reference is NOT a go string, everything will come crashing down catastrophically. And that go vet is configured to send you an angry message for doing this, reinforcing that this is indeed a bad idea.
UPDATE: Updated example to run on playground as of go 1.15.1, which either the playground or go itself has changed the way the memory is addressed. Or the more likely case that changes in core libs/runtime will shift the address across versions. It now dynamically obtains the address vs a manually hardcoded value.
package main
import "C"
import (
"log"
"strconv"
"unsafe"
)
func main() {
// parse the string into an integer value
addr, _ := strconv.ParseInt("0x1040c108", 0, 64)
// cast the integer to a c string pointer
ptr := (*C.char)(unsafe.Pointer(uintptr(addr)))
// convert to a go string (this will segfault)
str := C.GoString(ptr)
// print it
log.Println(str)
}
Yes!! you can store the address in a pointer variable and print its value by derefrencing it
i := "something"
ptr := &i
fmt.Println(*ptr)
For accessing the memory using a hard coded address such as 0x1040c108, it is necessary for your program to have access to that memory address otherwise, you will get an error saying invalid indirection of a pointer or segmentation fault.

Map of channels

I'd like to index some channels based on a string. I am using a map but it won't allow me to assign a channel to it. I keep getting "panic: assignment to entry in nil map", what am i missing?
package main
import "fmt"
func main() {
var things map[string](chan int)
things["stuff"] = make(chan int)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
https://play.golang.org/p/PYvzhs4q4S
You need to initialize the map first. Something like:
things := make(map[string](chan int))
Another thing, you're sending and trying to consume from an unbuffered channel, so the program will be deadlocked. So may be use a buffered channel or send/consume in a goroutine.
I used a buffered channel here:
package main
import "fmt"
func main() {
things := make(map[string](chan int))
things["stuff"] = make(chan int, 2)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
Playground link: https://play.golang.org/p/DV_taMtse5
The make(chan int, 2) part makes the channel buffered with a buffer length of 2. Read more about it here: https://tour.golang.org/concurrency/3

How to convert from []byte to int in Go Programming

I need to create a client-server example over TCP. In the client side I read 2 numbers and I send them to the server. The problem I faced is that I can't convert from []byte to int, because the communication accept only data of type []byte.
Is there any way to convert []byte to int or I can send int to the server?
Some sample code will be really appreciated.
Thanks.
You can use encoding/binary's ByteOrder to do this for 16, 32, 64 bit types
Play
package main
import "fmt"
import "encoding/binary"
func main() {
var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
data := binary.BigEndian.Uint64(mySlice)
fmt.Println(data)
}
If []byte is ASCII byte numbers then first convert the []byte to string and use the strconv package Atoi method which convert string to int.
package main
import (
"fmt"
"strconv"
)
func main() {
byteNumber := []byte("14")
byteToInt, _ := strconv.Atoi(string(byteNumber))
fmt.Println(byteToInt)
}
Go playground
Starting from a byte array you can use the binary package to do the conversions.
For example if you want to read ints :
buf := bytes.NewBuffer(b) // b is []byte
myfirstint, err := binary.ReadVarint(buf)
anotherint, err := binary.ReadVarint(buf)
The same package allows the reading of unsigned int or floats, with the desired byte orders, using the general Read function.
now := []byte{0xFF,0xFF,0xFF,0xFF}
nowBuffer := bytes.NewReader(now)
var nowVar uint32
binary.Read(nowBuffer,binary.BigEndian,&nowVar)
fmt.Println(nowVar)
4294967295
The math/big provides a simple and easy way to convert a binary slice to a number
playground
package main
import (
"fmt"
"math/big"
)
func main() {
b := []byte{0x01, 0x00, 0x01}
v := int(big.NewInt(0).SetBytes(b).Uint64())
fmt.Printf("%v", v)
}
For encoding/decoding numbers to/from byte sequences, there's the encoding/binary package. There are examples in the documentation: see the Examples section in the table of contents.
These encoding functions operate on io.Writer interfaces. The net.TCPConn type implements io.Writer, so you can write/read directly to network connections.
If you've got a Go program on either side of the connection, you may want to look at using encoding/gob. See the article "Gobs of data" for a walkthrough of using gob (skip to the bottom to see a self-contained example).
Using bitwise operator without additional dependencies
func toInt(bytes []byte) int {
result := 0
for i := 0; i < 4; i++ {
result = result << 8
result += int(bytes[i])
}
return result
}
binary.Read in encoding/binary provides mechanisms to convert byte arrays to datatypes.
Note that Network Byte Order is BigEndian, so in this case, you'll want to specify binary.BigEndian.
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
func main() {
var myInt int
b := []byte{0x18, 0x2d} // This could also be a stream
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.BigEndian, &myInt) // Make sure you know if the data is LittleEndian or BigEndian
if err != nil {
fmt.Println("binary.Read failed:", err)
return
}
fmt.Print(myInt)
}
Reviewing this documentation may be helpful: https://pkg.go.dev/encoding/binary#go1.17.1#Read
If bytes in the []byte array are ASCII characters from 0 to 9 you can convert them to an int in a loop:
var value int
for _, b := range []byte{48, 49, 50, 51, 52} {
value = value*10 + int(b-48)
}
fmt.Printf("integer value: %d", value)
Go Playground

Resources