What are the differences between a *string and a string in Golang? - string

Aim: understanding the difference between *string and string in Golang
Attempt
func passArguments() {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
fmt.Printf("Your username is %q.", username)
}
results in:
Your username is "root".Your username is %!q(*string=0xc820072200)
but when the *string is assigned to a string:
bla:=*username
fmt.Printf("Your username is %q.", bla)
it is able to print the string again:
Your username is "root".Your username is %!q(*string=0xc8200781f0).Your username is "root".
Questions
Why is a *string != string, e.g. display of: "root" vs.
%!q(*string=0xc8200781f0)?
In what other cases should a *string be
used instead of a string and why?
Why is it possible to assign a
*string to a string variable, while the display of the string is different, e.g. display of: "root" vs.
%!q(*string=0xc8200781f0)?

A *string is a pointer to a string. If you're not familiar with pointers, let's just say that it's a value that holds the address of another value, instead of the value itself (it's a level of indirection).
When a * is used in a type, it denotes a pointer to that type. *int is a pointer to an integer. ***bool is a pointer to a pointer to a pointer to a bool.
flag.String returns a pointer to a string because it it can then modify the string value (after the call to flag.Parse) and you are able to retrieve that value using the dereference operator - that is, when using * on a variable, it dereferences it, or retrieves the value pointed to instead of the value of the variable itself (which in the case of a pointer would just be a memory address).
So to answer your specific questions:
the %q verb in the fmt package understands strings (and slices of bytes), not pointers, hence the apparent gibberish displayed (when a value is not of the expected type for the matching verb - here %q - the fmt functions display %!q along with the actual type and value passed)
A pointer to a string is very rarely used. A string in Go is immutable (https://golang.org/ref/spec#String_types) so in cases like flag.String where you need to return a string that will be mutated later on, you have to return a pointer to a string. But you won't see that very often in idiomatic Go.
You are not assigning a *string (pointer to a string) to a string. What you are doing, as I mentioned earlier, is dereferencing the *string variable, extracting its string value. So you are in fact assigning a string to a string. Try removing the * on that line, you'll see the compiler error message. (actually, because you're using the short variable declaration notation, :=, you won't see a compiler error, but your variable will be declared as a pointer-to-a-string. Try this instead, to better understand what's going on:
var s string
s = username
That will raise the compiler error).

Related

Is string a reference type or a value type

I was recently reading the source code of go. I see that there is a file called string.go in the source code, but at the same time, the string is the predeclared identifiers, and it also being used in the source code directly?
I found some article that said string is the reference type. but I try to run the following code:
func TestString(t *testing.T) {
s := "abc"
fmt.Println("address of s: ", &s)
xx := func(sss string) {
fmt.Println("address of sss: ", &sss)
sss = "123"
}
xx(s)
fmt.Println("value of s after sss modified the content: ", s)
}
output:
=== RUN TestString
address of s: 0xc00010a560
address of sss: 0xc00010a570
value of s after sss modified the content: abc
--- PASS: TestString (0.00s)
if the string is reference, So when I pass the s to func(sss string), the address of sss should be the same with s, and s should be modified, but it wasn't, why?
Is the go did something of string, let it seems like a value type? but where is the code? if the string is a refernce type and the actual type of string is type stringStruct, it should be defined the behavior somewhere?
It really confuse me
&s and &sss are the addresses of variables. Since they are 2 distinct non-zero size variables, their addresses must be different, which you experience.
There are no reference types in Go in the classic C sense. A string is a small struct-like value described by reflect.StringHeader:
type StringHeader struct {
Data uintptr
Len int
}
It contains a pointer where the UTF-8 encoded bytes of the string are stored, and a byte-length.
When you assign something to a variable of string type, you change the value of the variable (the above small StringHeader struct), but not the pointed data. When you assign something to the sss variable, the original s variable is unchanged, it still contains the same data pointer pointing to the same bytes.
Read The Go Blog: Strings, bytes, runes and characters in Go
See related questions:
Immutable string and pointer address
What is the difference between the string and []byte in Go?

How can I get the byte representation of a format!() String in a single expression?

I am trying to format a string and then, in one expression, get a slice of u8s containing the byte representation of the string.
Running
format!("bedrijfpda{:0>3}", num).as_bytes()
gives me a temporary value dropped while borrowed error, but running
let val = format!("bedrijfpda{:0>3}", num);
let bytes = val.as_bytes();
gives me the result I want.
How can I do this in one expression?
You cannot. If this must be a single expression (maybe your hard drive is full and cannot store the newlines?), convert it to a Vec<u8>:
format!("").into_bytes();

How to compare a string with a bytes32 value?

I'm trying to check that a string value is equal to a bytes32 value in Solidity, like stringValue == bytes32Value.
As you can see in:
Variable values in Truffle Debugging
both variables have the same content. But how can I compare them?
See if this post helps - https://ethereum.stackexchange.com/a/9152
First, the string is read in as bytes using bytes method, which is used to perform empty string test, and then it leverages assembly method to return bytes32 representation of provided string.
Moreover, solidity documentation points to byte initialization techniques from string

Go - Comparing strings/byte slices input by the user

I am getting input from the user, however when I try to compare it later on to a string literal it does not work. That is just a test though.
I would like to set it up so that when a blank line is entered (just hitting the enter/return key) the program exits. I don't understand why the strings are not comparing because when I print it, it comes out identical.
in := bufio.NewReader(os.Stdin);
input, err := in.ReadBytes('\n');
if err != nil {
fmt.Println("Error: ", err)
}
if string(input) == "example" {
os.Exit(0)
}
string vs []byte
string definition:
string is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text. A string may be empty, but not nil. Values of string type are immutable.
byte definition:
byte is an alias for uint8 and is equivalent to uint8 in all ways. It is used, by convention, to distinguish byte values from 8-bit unsigned integer values.
What does it mean?
[]byte is a byte slice. slice can be empty.
string elements are unicode characters, which can have more then 1 byte.
string elements keep a meaning of data (encoding), []bytes not.
equality operator is defined for string type but not for slice type.
As you see they are two different types with different properties.
There is a great blog post explaining different string related types [1]
Regards the issue you have in your code snippet.
Bear in mind that in.ReadBytes(char) returns a byte slice with char inclusively. So in your code input ends with '\n'. If you want your code to work in desired way then try this:
if string(input) == "example\n" { // or "example\r\n" when on windows
os.Exit(0)
}
Also make sure that your terminal code page is the same as your .go source file. Be aware about different end-line styles (Windows uses "\r\n"), Standard go compiler uses utf8 internally.
[1] Comparison of Go data types for string processing.

what is string strName<>?

I have seen code like this:
struct failed_login_res {
string errorMsg<>;
unsigned int error;
};
What does the <> at the end mean? How is it different from normal declaration like string errorMsg?
Correction: this is for RPC stub, not C++ and I can confirm that it does compile. The question is then still valid.
From a quick googling, I came across this PDF.
Section 6.9 is as follows:
Strings: C has no built-in string type, but instead uses the null-terminated “char *” convention. In XDR language, strings are declared using the “string” keyword, and compiled into “char *”s in the output header file. The maximum size contained in the angle brackets specifies the maximum number of characters allowed in the strings (not counting the NULL character). The maximum size may be left off, indicating a string of arbitrary length.
Examples:
string name<32>; --> char *name;
string longname<>; --> char *longname;

Resources