Don't understand func strings.TrimLeft in Go - go

I'm trying to test code that uses func strings.TrimLeft. I needed to see an MVCE of it in action, so I went to the API specification.
It came with an example, which I exported, with the following code:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡"))
}
Upon running it, you get Hello, Gophers!!!
I decided to prepend the input string, changing the code to
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Print(strings.TrimLeft("irrelevant text¡¡¡Hello, Gophers!!!", "!¡"))
}
The result string is the whole input string: irrelevant text¡¡¡Hello, Gophers!!!
Aren't at least the cutset characters supposed to be removed?!

It is an industry standard that trim implies a proper suffix or prefix.
trimLeft will only remove matching characters from the beginning of the string and stop on the first non-match. In your example, the "i" of "irrelevant" is the first character it checks. It fails the check, so it stops trimming (i.e. it does nothing).
trimRight, by comparison, removes matches starting from the end of the string in descending index order.

Aren't at least the cutset characters supposed to be removed?!
All of the ones at the beginning of the string. There are zero of those, so zero characters are removed.

Related

Why is Go's escape analysis behaving differently when simple type is passed to two different functions with same signature

I don't quite get why Go's escape analysis says that a local integer variable escapes to the heap when it is passed to fmt.Fprintln while it is not escaping when it is passed to another self-written function with the same signature as fmt.Fprintln. I hope the two scenarios A and B below should make the problem more clear.
Scenario A: x escapes to heap
Take the following content of main.go:
package main
import (
"fmt"
"os"
)
func main() {
x := 73
fmt.Fprintln(os.Stdout, x)
}
When you now run go build -gcflags "-m" you see an output that indicates that the x escapes to the heap. The output says something along the lines of
...
.\main.go:10:14: x escapes to heap
...
Scenario B: x does not escape to heap
Now take the following content of main.go:
package main
import (
"io"
"os"
)
func main() {
x := 73
myOwnPrintFunction(os.Stdout, x)
}
//go:noinline
func myOwnPrintFunction(w io.Writer, a ...interface{}) {
println(a)
}
Running go build -gcflags "-m" again you see an output that indicates that x no longer escapes to the heap. The output now says something along the lines of
...
.\main.go:10:20: x does not escape
...
I don't get the difference here. I would have thought that scenario A is correct since x is passed to a variadic function that accepts an arbitrary number of interface{} arguments. But apparently that's wrong since the variable no longer escapes when it is passed to the self-written function myOwnPrintFunction which is also a variadic function accepting an arbitrary number of interface{} arguments and where the compiler is instructed to not inline this simple function.

Regular Expression with If Else Condition

I have a problem with If Else Condition in Regex. I have a file which contains the below format. I was looking for return value to be either 0.0.985 or 3.3.5-3811.
I was trying to use if else condition in regex but unable to do so, can anyone explain me while solving the problem please.
random-app-0.0.985.tgz
busy-app-7.3.1.2-3.3.5-3811-a19874elkc-123254376584.zip
Below is the Go code I am trying to use
package main
import (
"fmt"
"io/ioutil"
"regexp"
)
func main(){
content, err:= ioutil.ReadFile("version.txt")
if err != nil{
fmt.Println(err)
}
version:= string(content)
re:= regexp.MustCompile(`(\d+).(\d+).(\d+)|(\d+).(\d+).(\d+).(\d+)`)
result:= re.FindAllStringSubmatch(version,-1)
for i:= range(result){
fmt.Println(result[i][0])
}
}
Output is coming like
0.0.985
7.3.1
2-3.3
5-3811
19874
123254376584
The following regexp can be used: [\d\.]+[\.-][\d]{2,}
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`(?m)[\d\.]+[\.-][\d]{2,}`)
var str = `random-app-0.0.985.tgz
busy-app-7.3.1.2-3.3.5-3811-a19874elkc-123254376584.zip`
for i, match := range re.FindAllString(str, -1) {
fmt.Println(match, "found at index", i)
}
}
The output
0.0.985 found at index 0
3.3.5-3811 found at index 1
playground
?m multi line modifier. Causes ^ and $ to match the begin/end of each line (not only begin/end of string). In this case it does not make to much difference. It will work without it.
[\d\.]+ matches at least once (quantifier +) a sequence of a digit or a dot
[\.-] matches a dot or a hypen
[\d]{2,} matches at least two digits (quantifier {2,})
One problem with your code is that in a regular expression . matches any character but you're intending it to match a literal dot. Use \. or [.] instead.

TrimRight not working as I expected

Below is the code of TrimRight, on latest Go version
I am observing a behavior, which maybe I am misunderstanding but as my understanding, the below code should throw output as
Hello
But the output is coming as
Hell
Why is that so ? Note, I have kept a space before the Gophers in cutset, so fundamentally it should remove the " Gophers" from the primary string, leaving behind just Hello
package main
import (
"fmt"
"strings"
)
func main() {
result := strings.TrimRight("Hello Gophers", " Gophers")
fmt.Println(result, len(result))
}
As documented, TrimRight removes all matching characters from the right. Because o is included in your list (" Gophers"), it is also trimmed. If you want to trim that exact substring use TrimSuffix instead.

prevent json.Marshal time.Time removing trailing zeros

I have code similar to the following
package main
import (
"fmt"
"time"
"encoding/json"
)
type Message struct {
Time time.Time `json:"timestamp,omitempty"`
}
func main() {
t, _ := time.Parse("2006-01-02T15:04:05.999Z07:00", "2017-05-01T15:04:05.630Z")
msg := Message{
Time: t,
}
bs, _ := json.Marshal(msg)
fmt.Println(string(bs[:]))
}
This prints
{"timestamp":"2017-05-01T15:04:05.63Z"}
How can I make json marshalling keep the trailing 0? I.e., to print this?
{"timestamp":"2017-05-01T15:04:05.630Z"}
Edit:
Here's the playground https://play.golang.org/p/9p3kWeiwu2
time.Time always marshals to RFC 3339, only including sub-second precision if present: https://golang.org/pkg/time/#Time.MarshalJSON
You can write your own custom version using a named time.Time type, or you can define a custom marshal function for your structure, or you can make your structure hold a string in that place instead. In any case, if you want to use the same format, but including trailing zeros, you need to use a modified version of the RFC3339Nano constant.
Its value is: "2006-01-02T15:04:05.999999999Z07:00".
The 9's at the end mean "include until the rightmost non-zero value, omit after that". If you change those 9's to 0's, it will always include them. For example, if you always want millisecond precision (and nothing after that, regardless of whether it's non-zero or not), you would use:
"2006-01-02T15:04:05.000Z07:00"
If you feed that to Format() on your time.Time value, you'll get out the string you want, and can thus include it in the JSON.
Functioning example: https://play.golang.org/p/oqwnma6odw

Unable to use backslash `\` in Golang os.Arg variable

I have made a program in Golang and I am trying to use a file as the first argument when launching my program.
For example: ./goprogram.exe C:\Acidic\image.png
When my program tries to use the os.Arg[1] variable which should be the link to the image.png file, it returns the string without any of the backslashes (C:Acidicimage.png).
How can I use the whole string of an argument without characters being escaped?
I have made a little example:
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) >= 2 {
fmt.Println(os.Args[1])
}
}
I run go run args.go C:\Users\image.png and it outputs C:Usersimage.png
Put any argument between quotes:
./goprogram.exe "C:\Acidic\image.png"
The issue appears to be your shell. Try quoting the file path:
./goprogram.exe 'C:\Acidic\image.png' # prevents escape sequence execution
A string fo type C:\Acidic\image.png (with single \'s) is not a valid string in Go (invalid escape sequence \A, etc) and would not even compile.

Resources