How to concatenate strings and ints natively? - go

The shortest (cleanest) way I have found so far to concatenate strings with ints in Go is the following:
"blahblah" + strconv.Itoa(42) + "something"
(importing package strconv)
Since one motto of the Go language is to be simple, I was surprised to have to import a package to do this.
Hence, my question: is there any native (thus cleaner) way of doing this?
Obviously, I tried the following syntax, which does not even compile:
"blahblah" + 42 + "something"
I also tried that one, which is in fact a cast of the value, which is not what I want (it converts the value to the corresponding unicode character, which would be * for the value 42):
"blahblah" + string(42) + "something"

This'll do the trick (it uses reflection though):
str := fmt.Sprintf("blah %d blah", 42)

You can use different print commands to do what you want. It's not a one liner, but it works.
package main
import "fmt"
func main() {
fmt.Print("blahblah")
fmt.Print(42)
fmt.Print("something")
}
Playground

Related

How to split a string but keep delimiters as separate elements

I have several strings that include various symbols like the following two examples:
z=y+x
#symbol
and I want to split the strings such that I have the resulting slices:
[z = y + x]
[# symbol]
A few things I've looked at and tried:
I've looked at this question but it seems as though golang doesn't support lookarounds.
I know this solution exists using strings.SplitAfter, but I'm looking to have the delimiters as separate elements.
I tried replacing the symbol (e.g. "+") with some variant (e.g. "~+~") and doing a split on the surrounding characters (e.g. "~"), but this solution is far from elegant and runs into problems if I need to do a conditional replacement depending on the symbol (which golang doesn't seem to support either).
Perhaps I've misunderstood some of the previous question and their respective solutions.
I used a modified version of Go's strings.Split implementation https://golang.org/src/strings/strings.go?s=7505:7539#L245
func Test(te *testing.T) {
t := tester.New(te)
t.Assert().Equal(splitCharsInclusive("z=y+x", "=+"), []string{"z", "=", "y", "+", "x"})
t.Assert().Equal(splitCharsInclusive("#symbol", "#"), []string{"", "#", "symbol"})
}
func splitCharsInclusive(s, chars string) (out []string) {
for {
m := strings.IndexAny(s, chars)
if m < 0 {
break
}
out = append(out, s[:m], s[m:m+1])
s = s[m+1:]
}
out = append(out, s)
return
}
This is limited to single characters to split on. And passing something like splitCharsInclusive("(z)(y)(x)", "()") might not get you the output you want, as you'd get a few empty strings in the response. But hopefully this is a good starting point for the modifications you need.
Also, Go's version that I've linked calculates the length of the output array in advance, this is a nice optimization that I've decided to omit, but would likely be good to add back.

Why would you use fmt.Sprint?

I really don't understand the benefit of using fmt.Sprint compared to add strings together with +. Here is an example of both in use:
func main() {
myString := fmt.Sprint("Hello", "world")
fmt.Println(myString)
}
and
func main() {
myString := "Hello " + "World"
fmt.Println(myString)
}
What is the differences and benefits of each?
In your example there are no real differences as you are Sprintf to simply concaternate strings. That is indeed something which can be solved more easily by using the '+' operator.
Take the following example, where you want to print a clear error message like "Product with ID '42' could not be found.". How does that look with your bottom approach?
productID := 42;
myString := "Product with ID '" + productID + "' could not be found."
This would give an error (mismatched types string and int), because Go does not have support for concatenate different types together.
So you would have to transform the type to a string first.
productID := 42
myString := "Product with ID '" + strconv.Itoa(productID) + "' could not be found."
And, this you would have to do for every single data type other than strings.
The fmt package in Go and similar formatting packages in almost any other language solve this by helping you with the conversions and keeping your strings clear of mass '+' operators.
Here is how the example would look like using fmt
product := 42
myString := fmt.Sprintf("Product with ID '%d' could not be found.", product)
Here %d is the formatting verb for 'print the argument as a number'. See https://golang.org/pkg/fmt/#hdr-Printing the various other ways of printing other types.
Compared to concatenating fmt allows you to write your strings in a clear way, separating the template/text from the variables. And, it simplifies printing data types other than strings a lot.
fmt.Sprint is good for concatenation different types of its parameters as it uses reflection under the hood. So, if you need to concat strings - use "+", it's much faster, but if you need to contact number and your profit fmt.Sprint just like that:
message := fmt.Sprint(500, "internal server error")
If you call a function with concatenated string as argument, you will have to evaluate argument prior to call. Then if function chooses not to act on argument (think logging when log level is lower then needed for printing), you already incurred the overhead of concatenation.
Very similar to your example, in one case you do concatenation and in other not.
With high volume of those operations it may become noticeable. Again, logging is a good example.
In specific case of Sprint, it is not that relevant of course, but perhaps it's good to be consistent?
Most of the arguments have already been written, exclude one. Localization with Sprintf is much easier and has better defined roles between programmer and localizator (someone who speaks foreign language). Of course not each app really needs that. Let's choose:
s := fmt.Sprintf(t('%s is %d and comes from %s'), name, age, place)
or
s := name + t(' is ') + strconv.Itoa(age) + t(' and comes from ') + place
Translation of fragments of text is confusing. Also sprintf allows you formatting number etc
Like #Erwin (accepted answer) said, "mismatched types" is a problem with concatenation and using "strconv" seems overly complicated.
var unixTime = time.Now().Unix()
fmt.Println("This doesn't work: "+ string(unixTime))
fmt.Println("Unix timestamp, base 10: "+ strconv.FormatInt(unixTime, 10))
fmt.Println("Unix timestamp, Itoa: "+ strconv.Itoa(int(unixTime)))
// This looks cleaner, in my opinion...
fmt.Println("Unix timestamp, Sprint: "+ fmt.Sprint(unixTime))
Since web development usually involves concatenation of long strings that aren't going to stdout, I see Sprint as a useful tool.

Re-map a number from one range to another

Is there any equivalent in go for the Arduino map function?
map(value, fromLow, fromHigh, toLow, toHigh)
Description
Re-maps a number from one range to another. That is, a value of
fromLow would get mapped to toLow, a value of fromHigh to toHigh,
values in-between to values in-between, etc
If not, how would I implement this in go?
Is there any equivalent in go for the Arduino map function?
The standard library, or more specifically the math package, does not offer such a function, no.
If not, how would I implement this in go?
By taking the original code and translating it to Go. C and Go are very related syntactically and therefore this task is very, very easy. The manual page for map that you linked gives you the code. A translation to go is, as already mentioned, trivial.
Original from the page you linked:
For the mathematically inclined, here's the whole function
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
You would translate that to something like
func Map(x, in_min, in_max, out_min, out_max int64) int64 {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
}
Here is an example on the go playground.
Note that map is not a valid function name in Go since there is already the map built-in type which makes map a reserved keyword. keyword for defining map types, similar to the []T syntax.

Go: Efficiently storing hex values in memory

I have two 16-byte hex values that relate to each other that I want to keep in memory in Go (so they only need to exist for the lifetime of the running process) that can be represented as a simple map like so:
{"aabbcc": "112233"}
Obviously I could represent these as a struct of two strings, but I'm just wondering if there's a faster (i.e. performance) or more memory-efficient way to store the strings in Go? I've only delved into Go lightly so far, so don't know the standard library well enough to know a good answer.
Edit: For an idea of what I'm getting at (in pseudo-code):
I've got two UUIDs from different sources, that are generated/received as strings:
uuid_a_1 = "aabb-1122-3344"
uuid_a_2 = "ddee-5566-7788"
I want to store these in relation to each other:
uuid_map[] = {uuid_a_1: uuid_a_2}
So that I can return one when I lookup the other:
return uuid_map[uuid_a_1]
I'm just curious if there's a more efficient way to store these in memory than a simple map of strings, as I may for example want to store several thousand during the lifetime of the process, and want to be able to key/value store these as quickly as possible (the idea being that because I know the exact size and type of the keys and values that I can do it fast).
As FUZxxl is suggesting you can encode the string to a byte array.
http://play.golang.org/p/7MYWTWSu2-
package main
import (
"encoding/hex"
"fmt"
"strings"
)
func main() {
b, err := hex.DecodeString(strings.Replace("df31a780-f640-11e3-a3ac-0800200c9a66", "-", "", -1))
if err != nil {
fmt.Println(err)
}
fmt.Println("Decoded:", b)
fmt.Println("Encoded:", hex.EncodeToString(b))
}

What is "A Tour of Go" trying to say? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
There are a few points in the tutorial that sort of leave you on your own without a clue or link if you're not in the know I guess. So I'm sorry about the length of these:
http://tour.golang.org/#15
Try printing needInt(Big) too
I'm guessing ints are allowed less bits than constants?
http://tour.golang.org/#21
the { } are required.
(Sound familiar?)
Which language is alluded to?
http://tour.golang.org/#25
(And a type declaration does what you'd expect.)
Why do we need the word type and the word struct? What was I supposed to expect?
http://tour.golang.org/#28
Why implicit zeroes in the constructor? This sounds like a dangerous design choice by Go. Is there a PEP or anything beyond http://golang.org/doc/go_faq.html on this?
http://tour.golang.org/#30
Make? Are there constructors? What's the difference between new and make?
http://tour.golang.org/#33
Where did delete come from? I didn't import it.
http://tour.golang.org/#36
What's the %v formatter stand for? Value?
http://tour.golang.org/#47
panic: runtime error: index out of range
goroutine 1 [running]:
tour/pic.Show(0x400c00, 0x40ca61)
go/src/pkg/tour/pic/pic.go:24 +0xd4
main.main()
/tmpfs/gosandbox-15c0e483_5433f2dc_ff6f028f_248fd0a7_d7c2d35b/prog.go:14 +0x25
I guess I broke go somehow....
package main
import "tour/pic"
func Pic(dx, dy int) [][]uint8 {
image := make([][]uint8, 10)
for i := range image {
image[i] = make([]uint8, 10)
}
return image
}
func main() {
pic.Show(Pic)
}
http://tour.golang.org/#59
I return error values when a function fails? I have to qualify every single function call with an error check? The flow of the program is uninterrupted when I write crazy code? E.g. Copy(only_backup, elsewhere);Delete(only_backup) and Copy fails....
Why would they design it like that?
#15:
I'm guessing int's are allowed less bits than constants?
Yes, exactly. According to the spec, "numeric constants represent values of arbitrary precision and do not overflow", whereas type int has either 32 or 64 bits.
#21:
Which language is alluded to?
None; it's alluding to #16, which says the same thing, in the same words, about for-loops.
#25 :
a type declaration does what you'd expect is a little unfortunate, I agree (as it assumes too much on what a reader could expect...) but it means you're defining a struct (with the struct keyword) and binding the type name "Vertex" to it, with the type Vertex part (see http://golang.org/ref/spec#Type_declarations)
#28:
the fact that uninitialized structs are zeroed is really really useful in many cases (many standard structs like buffers use it also)
It's not implicit in the contructor only. Look at this
var i int; fmt.Println(i)
This prints out 0. This is similar to something like java where primitive types have an implicit default value. booleans are false, integers are zero, etc. The spec on zero values.
#30:
new allocates memory and returns a pointer to it, while make is a special function used only for Slices, maps and channels.
See http://golang.org/doc/effective_go.html#allocation_new for a more in-depth explanation of make vs new
#33:
delete, like append or copy is one of the basic operators of the language. See the full list of them at: http://golang.org/ref/spec#Predeclared_identifiers
#36:
Yes, %v stands for "value". See http://golang.org/pkg/fmt/
#47:
try with this:
func Pic(dx, dy int) [][]uint8 {
image := make([][]uint8, dy) // dy, not 10
for x := range image {
image[x] = make([]uint8, dx) // dx, not 10
for y := range image[x] {
image[x][y] = uint8(x*y) //let's try one of the mentioned
// "interesting functions"
}
}
return image
}
#59:
The language's design and conventions encourage you to explicitly
check for errors where they occur (as distinct from the convention in
other languages of throwing exceptions and sometimes catching them).
In some cases this makes Go code verbose, but fortunately there are
some techniques you can use to minimize repetitive error handling.
(quoted from Error handling and Go )
I'm guessing int's are allowed less bits than constants?
yes, Numeric constants are high-precision values. An int in any language doesn't have near the precision of other numeric types.
Which language is alluded to?
No clue but it is backwards from C and Java where ( ) is required and { } is optional.
Why do we need the word type and the word struct? What was I supposed to expect?
If you're familiar with C, then it does what you'd expect.
Why implicit zeroes in the constructor?
It's not implicit in the contructor only. Look at this
var i int
fmt.Println(i)
This prints out 0. This is similar to something like java where primitive types have an implicit default value. booleans are false, integers are zero, etc.
Make? Are there constructors? What's the difference between new and make?
make accepts additional parameters for initializing the size of an array, slice, or map. new on the other hand just returns a pointer to a type.
type Data struct {}
// both d1 and d2 are pointers
d1 := new(Data)
d2 := &Data{}
As for are there constructors?, only if you make and reference them. This how one normally implements a constructor in Go.
type Data struct {}
func NewData() *Data {
return new(Data)
}
What's the %v formatter stand for? Value?
Yep
I return error values when a function fails? ... Why would they design it like that?
I felt the same way at first. My opinion has changed though. You can ignore errors from the std library if you like and not bother with it yourself, but once I had a handle on it, I personally find I have better (and more readable) error checking.
What I can say is when I was doing it wrong, it felt like repetitive error handling that felt unnecessary. When I finally started doing it right... well, what I just said above.

Resources