Problem in connection string with escaping char - go

Im trying to develop my first API using Go, but at beginning I run into a problem.
str := "sqlserver://DESKTOP-AAAC9AC#SQLEXPRESS?database=GolangPlay"
dsn := strings.Replace(str, "#", `\`, -1)
fmt.Println("CS be like : " + dsn)
_, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
My connection string must contains escaping tag '' (DESKTOP-AAAC9AC\SQLEXPRESS), so I thought that firstly I might in my str string replace escaping tag with #. So that later when calling the gorm function sqlserver.Open(string) replace the # with escaping tag, but I dont understand why this function returns error with double backslash
"failed to initialize database, got error parse "sqlserver://DESKTOP-AAAC9AC\SQLEXPRESS?database=GolangPlay": invalid character "\" in host name"
but my println returns that what exactly I want
CS be like : sqlserver://DESKTOP-AAAC9AC\SQLEXPRESS?database=GolangPlay
Please explain why this is happening and help in solving it

Related

How do we manage a '#' in the Rest API query parameter [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I am facing a challenge with extracting the complete value out of the query param.
For instance, I have a localhost:8080/myAPI?name=Shop & stop #1234
I have the issue with & as well but atleast the content after & is getting populated as a separate param. I wrote some logic to manage it.
Coming to #, the content after # is not at all getting populated. I am using net/http library.
Did anyone face the similar issue?
First, in URLs the & character has special meaning: it spearates query parameters. So if the data you encode in the URL contains & characters, it has to be escaped. url.QueryEscape() can show you how the escaped form looks like:
fmt.Println(url.QueryEscape("Shop & stop "))
It outputs:
Shop+%26+stop+
Note that & is escaped like %26, and also spaces are substituted with a + sign.
So your valid input URL should look like this:
rawURL := "http://localhost:8080/myAPI?name=Shop+%26+stop+#23452"
Use the net/url package to parse valid URLs, it also supports getting the parameter values and the fragment you're looking for (the fragment is the remaining part after the # character):
u, err := url.Parse(rawURL)
if err != nil {
panic(err)
}
fmt.Println(u.Query().Get("name"))
fmt.Println(u.Fragment)
This outputs:
Shop & stop
23452
Try the examples on the Go Playground.
The bytes &, # and space have special meaning in a URL. These bytes must be escaped when included in a query value.
Use url.Values to create the escaped query:
v := url.Values{}
v.Set("name", "Shop & Stop #23452")
q := v.Encode()
u := "http://localhost:8080/myAPI?" + q
fmt.Println(u) // prints http://localhost:8080/myAPI?name=Shop+%26+stop+%2323452
You can also construct the URL using the url.URL type instead of string concatenation.
v := url.Values{}
v.Set("name", "Shop & Stop #23452")
u := url.URL{Scheme: "http", Host: "localhost:8080", Path: "/myapi", RawQuery: v.Encode()}
s := u.String()
fmt.Println(s) // prints http://localhost:8080/myAPI?name=Shop+%26+stop+%2323452
The url package encodes the # as %23. Most http server libraries will decode the %23 back to #. Here's an example using Go's net/http package:
name := req.FormValue("name") // name is "Shop & Stop #23452"
Run a complete client and server example on the Go Playground.

How to escape a string with single quotes

I am trying to unquote a string that uses single quotes in Go (the syntax is same as Go string literal syntax but using single quotes not double quotes):
'\'"Hello,\nworld!\r\n\u1F60ANice to meet you!\nFirst Name\tJohn\nLast Name\tDoe\n'
should become
'"Hello,
world!
😊Nice to meet you!
First Name John
Last Name Doe
How do I accomplish this?
strconv.Unquote doesn't work on \n newlines (https://github.com/golang/go/issues/15893 and https://golang.org/pkg/strconv/#Unquote), and simply strings.ReplaceAll(ing would be a pain to support all Unicode code points and other backslash codes like \n & \r & \t.
I may be asking for too much, but it would be nice if it automatically validates the Unicode like how strconv.Unquote might be able to do/is doing (it knows that x Unicode code points may become one character), since I can do the same with unicode/utf8.ValidString.
#CeriseLimón came up with this answer, and I just put it into a function with more shenanigans to support \ns. First, this swaps ' and ", and changes \ns to actual newlines. Then it strconv.Unquotes each line, since strconv.Unquote cannot handle newlines, and then reswaps ' and " and pieces them together.
func unquote(s string) string {
replaced := strings.NewReplacer(
`'`,
`"`,
`"`,
`'`,
`\n`,
"\n",
).Replace(s[1:len(s)-1])
unquoted := ""
for _, line := range strings.Split(replaced, "\n") {
tmp, err := strconv.Unquote(`"` + line + `"`)
repr.Println(line, tmp, err)
if err != nil {
return nil, NewInvalidAST(obj.In.Text.LexerInfo, "*Obj.In.Text.Text")
}
unquoted += tmp + "\n"
}
return strings.NewReplacer(
`"`,
`'`,
`'`,
`"`,
).Replace(unquoted[:len(unquoted)-1])
}

Getting an error when trying to check path

I am trying to check windows dir in my golang app.
Here is my code
func createWalletDirectory(path string) (err error) {
_, err = os.Stat(path)
if os.IsNotExist(err) {
return err
}
path = filepath.FromSlash(path)
path = path + string(os.PathSeparator) + DirectoryName
err = os.Mkdir(path, 0666)
return
}
So on the first line of the function I am getting an error look like this
invalid character 'i' in string escape code
Example path : C:\Users
Note: The path I am getting from users via POST request
So I need to make a code which will check crossplatform paths.
How can I solve this error ?
You can use path package to work with the urls('path/filepath' for the file paths) which also contributes in platform independency. So you can do following to create the path
givenPath = filepath.Join(DirectoryName, path)
There is also another way of doing this
path := strings.Join([]string{DirectoryName, path}, string(os.PathSeparator))
In Go strings enclosed by double quotes, a backslash starts an escape code, e.g. \n or \u2318. To avoid this, you have two options:
use a double backslash (\\), e.g. "C:\\Users"
use backticks (`) instead of double quotes to define a "raw string", e.g. `C:\Users`
Further reading

Golang Sprintf formatting a string and using it multiple times

I try to generate a sql query using Sprintf() where I have to use the same variable two times
myStr := "test"
str := Sprintf("SELECT ... WHERE a = '%#[1]s' or b = '%#[1]s'", myStr)
fmt.Println(str)
This snippets outputs the expected string
SELECT ... WHERE a = 'test' or b = 'test'
but go vet says:
unrecognized printf flag for verb 's': '#' (vet)
And I am puzzled why. Switching the printf verb to v satisfies go vet but adds " around my string. And I honestly doesn't see a mistake in using %#[1]s.
Any thoughts?
Using printf to construct queries is a bad idea, it opens you up to SQL injection.
See named parameters in the sql package.
There is no # Sprintf flag for a string verb (the flag # is e.g. adding 0x for hex values: %#x). So remove it to make your go vet troubles disappear:
myStr := "test"
str := Sprintf("SELECT ... WHERE a = '%[1]s' or b = '%[1]s'", myStr)
fmt.Println(str)
But: If any part of your constructed query (myStr) comes from external input (i.e. user input), you really should follow Hein's advise and use named parameters.

Go regexp: match three asterisks

So I did this:
r, _ := regexp.Compile("* * *")
r2 := r.ReplaceAll(b, []byte("<hr>"))
and got:
panic: runtime error: invalid memory address or nil pointer dereference
So I figured I had to escape them:
r, _ := regexp.Compile("\* \* \*")
But got unknown escape secuence
I'm a Go Beginner. What am I doing wrong?
You are not checking errors.
regexp.Compile gives you two results:
the compiled pattern (or nil)
the error while compiling the pattern (or nil)
You are ignoring the error and accessing the nil result. Observe (on play):
r, err := regexp.Compile("* * *")
fmt.Println("r:", r)
fmt.Println("err:", err)
Running this code will show you that, indeed there is an error. The error is:
error parsing regexp: missing argument to repetition operator: *
So yes, you are right, you have to escape the repetition operator *. You tried the following:
r, err := regexp.Compile("\* \* \*")
And consequently you got the following error from the compiler:
unknown escape sequence: *
Since there are a number of escape sequences like \n or \r for special characters that you do not have on your keyboard but want to have in strings, the compiler tries to insert these characters. \* is not a valid escape sequence and thus the compiler fails to do the replacement. What you want to do is to escape the escape sequence so that the regexp parser can do its thing.
So, the correct code is:
r, err := regexp.Compile("\\* \\* \\*")
The simplest way of dealing with these kind of quirks is using the raw string literals ("``") instead of normal quotes:
r, err := regexp.Compile(`\* \* \*`)
These raw strings ignore escape sequences altogether.
Adding to #VonC's answer, regexp aren't always the answer and are generally slower than using strings.*.
For a complex expression, sure regexp is awesome, however if you just want to match a string and replace it then, strings.Replacer is the way to go:
var asterisksReplacer = strings.NewReplacer(`* * *`, `<hr>`)
func main() {
fmt.Println(asterisksReplacer.Replace(`xxx * * * yyy *-*-* zzz* * *`))
}
playground
Try escaping your '*' (since '*' is a special character used for repetition in the re2 syntax)
r, err := regexp.Compile(`\* \* \*`)
// and yes, always check the error
// or at least use regexp.MustCompile() if you want to fail fast
Note the use of back quotes `` for the string literal.

Resources