Convert Go rune to string - string

I am trying to convert s := '{"selector:"{"Status":"open"}"}' to type string, as I need to pass this as an argument to a query using GetQueryResult().
I have tried UnescapeString, it only accepts string as argument:
fmt.Println("args " ,html.UnescapeString(s)
but s is a Go rune.

The Go Programming Language Specification
String literals
Rune literals
Use string raw literal back quotes, not rune literal single quotes.
For example,
package main
import (
"fmt"
)
func main() {
s := `{"selector:"{"Status":"open"}"}`
fmt.Printf("type %T: %s", s, s)
}
Playground: https://play.golang.org/p/lGARb35VHTv
Output:
type string: {"selector:"{"Status":"open"}"}

Related

Replace a character in a string in golang

I am trying to replace a specific position character from an array of strings. Here is what my code looks like:
package main
import (
"fmt"
)
func main() {
str := []string{"test","testing"}
str[0][2] = 'y'
fmt.Println(str)
}
Now, running this gives me the error:
cannot assign to str[0][2]
Any idea how to do this? I have tried using strings.Replace, but AFAIK it will replace all the occurrence of the given character, while I want to replace that specific character. Any help is appreciated. TIA.
Strings in Go are immutable, you can't change their content. To change the value of a string variable, you have to assign a new string value.
An easy way is to first convert the string to a byte or rune slice, do the change and convert back:
s := []byte(str[0])
s[2] = 'y'
str[0] = string(s)
fmt.Println(str)
This will output (try it on the Go Playground):
[teyt testing]
Note: I converted the string to byte slice, because this is what happens when you index a string: it indexes its bytes. A string stores the UTF-8 byte sequence of the text, which may not necessarily map bytes to characters one-to-one.
If you need to replace the 2nd character, use []rune instead:
s := []rune(str[0])
s[2] = 'y'
str[0] = string(s)
fmt.Println(str)
In this example it doesn't matter though, but in general it may.
Also note that strings.Replace() does not (necessarily) replace all occurrences:
func Replace(s, old, new string, n int) string
The parameter n tells how many replacement are to be performed max. So the following also works (try it on the Go Playground):
str[0] = strings.Replace(str[0], "s", "y", 1)
Yet another solution could be to slice the string up until the replacable character, and starting from the character after the replacable one, and just concatenate them (try this one on the Go Playground):
str[0] = str[0][:2] + "y" + str[0][3:]
Care must be taken here too: the slice indices are byte indices, not character (rune) indices.
See related question: Immutable string and pointer address
Here's a function that will do that for you. It takes care of converting the string that you want to modify into a []rune, and then back out to string.
If your intention is to replace bytes rather than runes, you can:
copy this function's code, rename it from runeSub to byteSub
change the r rune parameter to b byte
Also available on repl.it
package main
import "fmt"
// runeSub - given an array of strings (ss), replace the
// (ri)th rune (character) in the (si)th string
// of (ss), with the rune (r)
//
// ss - the array of strings
// si - the index of the string in ss that you want to modify
// ri - the index of the rune in ss[si] that you want to replace
// r - the rune you want to insert
//
// NOTE: this function has no panic protection from things like
// out-of-bound index values
func runeSub(ss []string, si, ri int, r rune) {
rr := []rune(ss[si])
rr[ri] = r
ss[si] = string(rr)
}
func main() {
ss := []string{"test","testing"}
runeSub(ss, 0, 2, 'y')
fmt.Println(ss)
}

Golang convert integer to unicode character

Given the following input:
intVal := 2612
strVal := "2612"
What is a mechanism for mapping to the associated unicode value as a string.
For example, the following code prints "☒"
fmt.Println("\u2612")
But the following does not work:
fmt.Println("\\u" + strVal)
I researched runes, strconv, and unicode/utf8 but was unable to find a suitable conversion strategy.
2612 is not the integer value of the unicode rune, the integer value of \u2612 is 9746. The string "2612" is the hex value of the rune, so parse it as a hex number and convert it to a rune.
i, err := strconv.ParseInt(strVal, 16, 32)
if err != nil {
log.Fatal(err)
}
r := rune(i)
fmt.Println(string(r))
https://play.golang.org/p/t_e6AfbKQq
This one works:
fmt.Println("\u2612")
Because an interpreted string literal is specified in the source code, and the compiler will unquote (interpret) it. It is not the fmt package that processes this unquoting.
This doesn't work:
fmt.Println("\\u" + strVal)
Because again an interpreted string literal is used which will be resolved to a string value \u, and then it will be concatenated with the value of the local variable strVal which is 2612, so the final string value will be \u2612. But this is not an interpreted string literal, this is the "final" result. This won't be processed / unquoted further.
Alternatively to JimB's answer, you may also use strconv.Unquote() which does an unquoting similar to what the compiler does.
See this example:
// The original that works:
s := "\u2612"
fmt.Println(s, []byte(s))
// Using strconv.Unquote():
strVal := "2612"
s2, err := strconv.Unquote(`"\u` + strVal + `"`)
fmt.Println(s2, []byte(s2), err)
fmt.Println(s == s2)
Output (try it on the Go Playground):
☒ [226 152 146]
☒ [226 152 146] <nil>
true
Something to note here: We want to unquote the \u2612 text by strconv.Unquote(), but Unquote() requires that the string to be unquoted to be in quotes ("Unquote interprets s as a single-quoted, double-quoted, or backquoted Go string literal..."), that's why we pre- and postpended it with a quotation mark.

golang convert "type []string" to string

I see some people create a for loop and run through the slice as to create a string, is there an easier way to convert a []string to a string?
Will sprintf do it?
You can use strings.Join(arr \[\]string, separator string) string.
This is a simple example, which you can paste into the main function:
stringArray := []string {"Hello","world","!"}
justString := strings.Join(stringArray," ")
fmt.Println(justString)
And link to working example on playground.
Or using very simple function
simple function
Will Sprint do it?
Yes indeed!
Here is another way to convert to a string if all you care about is that it is a string and not specifically how it looks (see answers above with strings.Join for a little more flexibility).
The advantage of this method (or variations such as Sprintf), is it will work with (almost) every other data such as maps and structs and any custom type that implements the fmt.Stringer inteface.
stringArray := []string {"Hello","world","!"}
justString := fmt.Sprint(stringArray)
Here is a link to a working example.
It can be done easily using Join function by importing strings package. You need to pass the slice of strings and the separator you need to separate the elements in the string. (examples: space or comma)
func Join(elems []string, sep string) string
Example Code :
package main
import (
"fmt"
"strings"
)
func main() {
sliceStr := []string{"a","b","c","d"}
str := strings.Join(sliceStr,", ")
fmt.Println(str)
}
//output: a, b, c, d
If you don't care about the separator, you can use path:
package main
import "path"
func main() {
a := []string{"south", "north"}
s := path.Join(a...)
println(s == "south/north")
}
https://golang.org/pkg/path#Join
package main
import (
"fmt"
"reflect"
"strings"
)
func main() {
str1 := []string{"Trump", "In", "India", "On", "Feb 25"}
fmt.Println(str1)
fmt.Println(reflect.TypeOf(str1))
str2 := strings.Join(str1, " ")
fmt.Println(str2)
fmt.Println(reflect.TypeOf(str2))
str3 := strings.Join(str1, ", ")
fmt.Println(str3)
fmt.Println(reflect.TypeOf(str3))
}
Below is the ouput of the above program :-
go run hello.go
[Trump In India On Feb 25]
[]string
Trump In India On Feb 25
string
Trump, In, India, On, Feb 25
string
In the above code, first, we have defined a slice of string and then use the reflect package to determine the datatype of the slice.
We have imported the “strings” module. With strings.Join() method, and we combine all elements of a string slice into a string. So, Golang string.Join() function that converts slice to string. We have passed the space(” “) as a delimiter. So we will join the slice elements by space.
The second argument to strings.Join() is the delimiter. For no delimiter, please use an empty string literal.
In the next step, we have again used the TypeOf() function to check the data type.
Then we have used the Golang string.Join() function again, but this time, we have passed (,) Comma. So, command separated values will be returned, which is also a type of string.
So, if you want to get CSV values in Golang, then you can use the Go string.Join() method.
You can also try with functions:-
// abc.go
package main
type deck []string
func (cards deck) toString() string {
// converts slice to string
return strings.Join([]string(cards), ",")
}
//main.go
package main
import "fmt"
func main() {
cards := []string {"Trump", "In", "India", "On", "Feb 25"}
fmt.Println(cards.toString())
}

How to get a single Unicode character from string

I wonder how I can I get a Unicode character from a string. For example, if the string is "你好", how can I get the first character "你"?
From another place I get one way:
var str = "你好"
runes := []rune(str)
fmt.Println(string(runes[0]))
It does work.
But I still have some questions:
Is there another way to do it?
Why in Go does str[0] not get a Unicode character from a string, but it gets byte data?
First, you may want to read https://blog.golang.org/strings
It will answer part of your questions.
A string in Go can contains arbitrary bytes. When you write str[i], the result is a byte, and the index is always a number of bytes.
Most of the time, strings are encoded in UTF-8 though. You have multiple ways to deal with UTF-8 encoding in a string.
For instance, you can use the for...range statement to iterate on a string rune by rune.
var first rune
for _,c := range str {
first = c
break
}
// first now contains the first rune of the string
You can also leverage the unicode/utf8 package. For instance:
r, size := utf8.DecodeRuneInString(str)
// r contains the first rune of the string
// size is the size of the rune in bytes
If the string is encoded in UTF-8, there is no direct way to access the nth rune of the string, because the size of the runes (in bytes) is not constant. If you need this feature, you can easily write your own helper function to do it (with for...range, or with the unicode/utf8 package).
You can use the utf8string package:
package main
import "golang.org/x/exp/utf8string"
func main() {
s := utf8string.NewString("ÄÅàâäåçèéêëìîïü")
// example 1
r := s.At(1)
println(r == 'Å')
// example 2
t := s.Slice(1, 3)
println(t == "Åà")
}
https://pkg.go.dev/golang.org/x/exp/utf8string
you can do this:
func main() {
str := "cat"
var s rune
for i, c := range str {
if i == 2 {
s = c
}
}
}
s is now equal to a

Indexing string as chars

The elements of strings have type byte and may be accessed using the
usual indexing operations.
How can I get element of string as char ?
"some"[1] -> "o"
The simplest solution is to convert it to an array of runes :
var runes = []rune("someString")
Note that when you iterate on a string, you don't need the conversion. See this example from Effective Go :
for pos, char := range "日本語" {
fmt.Printf("character %c starts at byte position %d\n", char, pos)
}
This prints
character 日 starts at byte position 0
character 本 starts at byte position 3
character 語 starts at byte position 6
Go strings are usually, but not necessarily, UTF-8 encoded. In the case they are Unicode strings, the term "char[acter]" is pretty complex and there is no generall/unique bijection of runes (code points) and Unicode characters.
Anyway one can easily work with code points (runes) in a slice and use indexes into it using a conversion:
package main
import "fmt"
func main() {
utf8 := "Hello, 世界"
runes := []rune(utf8)
fmt.Printf("utf8:% 02x\nrunes: %#v\n", []byte(utf8), runes)
}
Also here: http://play.golang.org/p/qWVSA-n93o
Note: Often the desire to access Unicode "characters" by index is a design mistake. Most of textual data is processed sequentially.
Another option is the package utf8string:
package main
import "golang.org/x/exp/utf8string"
func main() {
s := utf8string.NewString("🧡💛💚💙💜")
t := s.At(2)
println(t == '💚')
}
https://pkg.go.dev/golang.org/x/exp/utf8string

Resources