Read Space Seperated Strings in Golang 1.8 - go

Hi I have two problems in the following Go Program .
1. I couldn't read the space seperated string using Scanf or Scanln.
So I have added a formatted string "%q" to read space seperated string using double quotes.
Is there an alternative to read string with spaces ?
package main
import
(
"fmt"
"strings"
)
type details struct{
DataType string
Table string
}
func main(){
dt := details{}
fmt.Println("Enter the DataType")
fmt.Scanf("%q" ,&dt.DataType )
for strings.TrimSpace(dt.DataType) == "" {
fmt.Println("Enter the DataType")
fmt.Scanln(&dt.DataType)
}
//fmt.Println(dt.DataType)
fmt.Println("Enter the Table")
fmt.Scanln(&dt.Table)
for strings.TrimSpace(dt.Table) == "" {
fmt.Println("Enter a valid Table name ")
fmt.Scanln(&dt.Table)
}
}
The Console output is as follows ,
VenKats-MacBook-Air:ColumnCreator venkat$ go run test.go
Enter the DataType
"rid bigint not null"
Enter the Table
Enter a valid Table name
The Second problem is why does the control flow went to the second for loop without waiting for the user input . Does the Scanf with "%q" returned a carraige return .
Any help would be greatly appreciated

Perhaps something like this..
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type details struct {
DataType string
Table string
}
func main() {
dt := details{}
cin := bufio.NewReader(os.Stdin)
for {
fmt.Println("Enter the DataType")
text, err := cin.ReadString('\n') // reads entire string up until the /n which is the newline deliminator
if strings.TrimSpace(text) == "" { // check to see if the input is empty
continue
}
if err == nil { // if the input is not empty then the control got this far and now we just have to check for error, assign the data, and break out of the loop .. repeat for the second input. If this is going to be something you do alot refactor the input section.
dt.DataType = text
break
} else {
fmt.Printf("An error as occured: %s\n", err.Error())
}
}
for {
fmt.Println("Enter the Table")
text, err := cin.ReadString('\n')
if strings.TrimSpace(text) == "" {
continue
}
if err == nil {
dt.Table = text
break
} else {
fmt.Printf("An error as occured: %s\n", err.Error())
}
}
fmt.Printf("%+v\n", dt)
return
}
Example of refactored code:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type details struct {
DataType string
Table string
}
func getInput(message string, reader bufio.Reader) (input string) {
for {
fmt.Println(message)
input, err := reader.ReadString('\n')
if strings.TrimSpace(input) == "" {
continue
}
if err == nil {
break
} else {
fmt.Printf("An error as occured: %s\n", err.Error())
}
}
return
}
func main() {
dt := details{}
cin := bufio.NewReader(os.Stdin)
t := getInput("Enter the DataType", *cin)
dt.DataType = t
t = getInput("Enter the Table", *cin)
dt.Table = t
fmt.Printf("Seeing what my data looks like %+v\n", dt)
return
}

Related

Go printing wierd output

When I execute below code in Online Go compiler it works as expected, but when I execute this code in my computer(Golang 1.17.5). It prints weird output.
package main
import (
"fmt"
"os"
)
//variables
var (
countries = []string{"au", "in", "jp", "kr", "tr"}
country string
)
//main function
func main() {
if len(os.Args) < 2 {
fmt.Printf("country code : ")
fmt.Scanf("%s", &country)
checkcountry(&country)
// log.Printf("")
} else {
checkcountry(&country)
}
}
//check whether the entered string is in countries string_array
func checkcountry(country *string) {
for 1 == 1 {
if is_string_in_array(*country, countries) {
fmt.Printf("country : %s, breaking\n", *country)
break
} else {
fmt.Printf("country code : ")
fmt.Scanf("%s", country)
}
}
}
func is_string_in_array(str string, array []string) bool {
for _, i := range array {
if str == i {
return true
}
}
return false
}
repl.it terminal output :
go run main.go
country code : dd
country code :
my terminal output :
go run main.go
country code : dd
country code : country code :
Instead of fmt.Scanf you can use bufio package to read input as shown in below example which parse input till newline.
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter text: ")
text, _ := reader.ReadString('\n')
fmt.Println(text)
Rather than using fmt.Scanf you should probably use bufio.Scanner which is a little smarter in detecting newlines and whitespace.
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Country code:")
scanner.Scan()
text := scanner.Text()
fmt.Println(text)
}

Regex Matching in golang

How do you match the string ello w in hello world
Got to this error from trying this example
package main
import (
"fmt"
"regexp"
)
func check(result string ) string {
if (regexp.MatchString("b\\ello w\\b",result)) {
fmt.Println("Found it ")
return "True"
} else {
return "False"
}
}
func main() {
text := "Hello world "
check (text)
}
throws the following error
# command-line-arguments
.\test.go:14:5: multiple-value regexp.MatchString() in single-value context
regexp.MatchString returns two value. When you use it in your if conditional, compiler fails.
You should assign the return values first, then handle error case and then the match case
By the way your regex was also faulty, please see the code for a correct one for your case
https://play.golang.org/p/dNEsa9mIfhE
func check(result string ) string {
// faulty regex
// m, err := regexp.MatchString("b\\ello w\\b",result)
m, err := regexp.MatchString("ello w",result)
if err != nil {
fmt.Println("your regex is faulty")
// you should log it or throw an error
return err.Error()
}
if (m) {
fmt.Println("Found it ")
return "True"
} else {
return "False"
}
}
func main() {
text := "Hello world "
check(text)
}
MatchString() returns 2 values, a bool and an error, so your if statement doesn't know how to process that. https://pkg.go.dev/regexp#MatchString
In the correction below, I just through away the error value but I would recommend actually checking and handling the error.
https://play.golang.org/p/awAFxxAMyWl
package main
import (
"fmt"
"regexp"
)
func check(result string ) string {
found, _:= regexp.MatchString(`ello w`,result)
if (found) {
fmt.Println("Found it ")
return "True"
} else {
return "False"
}
}
func main() {
text := "Hello world "
fmt.Println(check(text))
}

String and integer concatenation issues golang

I am trying to write a port scanner in Go, i am facing few problems since i am new to this. Below is the code i have written till now.
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
callme()
}
func callme() {
var status string
getip := os.Args[1]
getport := 0
for i := 0; i < 10; i++ {
getport += i
data := getip + ":" + getport
conn, err := net.Dial("tcp", data)
if err != nil {
log.Println("Connection error:", err)
status = "Unreachable"
} else {
status = getport + " - " + "Open"
defer conn.Close()
}
fmt.Println(status)
}
}
I take ip from user as a command line arg, and then want to scan all ports on this ip. Since the net.Dial function needs data in a format like "ip:port" i am kinda confused how to concat string and int each time. Can any1 help me achieve this ?
One possibility is using strconv.Itoa(getport) to convert the int into a string. Another possibility is formatting the string, as in fmt.Sprintf("%s:%d", getip, getport) or fmt.Sprintf("%d - Open", getport).

Error embedding "\n" into a string literal

I need to decode a JSON string which has "\n" in it:
[
{"Name":"Neo", "Message":"Hi\n:Hello everyone"},
{"Name":"Sam","Messsage":"Hello\nEveery\nOne"}
]
I use the Golang code below:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Messages []string `json:"Name,omitempty"`
}
func main() {
s := "[{\"Name\":\"Neo\", \"Message\":\"Hi\n:Hello everyone\"}, {\"Name\":\"Sam\",\"Messsage\":\"Hello\nEveery\nOne\"}]"
var pro Person
err := json.Unmarshal([]byte(s), &pro)
if err == nil {
fmt.Printf("%+v\n", pro)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", err)
}
}
But I get the error:
ERROR invalid character '\n' in string literal
There are a few of issues here. The first is that newline is not allowed in a JSON string. Use the two bytes \n to specify a newline, not an actual newline. If you use an interpreted string literal, then the \ must be quoted with a \. Example:
"Hello\\nWorld"
No quoting is required in a raw string literal:
`Hello\nWorld`
The next issue is that JSON value is an array of object values. To handle the array, unmarshal to a slice:
var pro []Person
err := json.Unmarshal([]byte(s), &pro)
To handle the objects, define Person as a struct:
type Person struct {
Name string
Message string
}
working example on the playground.
Use backtick, like this working sample code:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"Name"`
Message string `json:"Message"`
}
func main() {
s := `
[
{"Name":"Neo", "Message":"Hi\n:Hello everyone"},
{"Name":"Sam", "Message":"Hello\nEvery\nOne"}
]
`
var pro []Person
err := json.Unmarshal([]byte(s), &pro)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%q\n", pro)
fmt.Println()
fmt.Println(pro)
}
output:
[{"Neo" "Hi\n:Hello everyone"} {"Sam" "Hello\nEvery\nOne"}]
[{Neo Hi
:Hello everyone} {Sam Hello
Every
One}]

How do I write a function that accepts both string and int64 types in Go?

I have function that looks like this
func GetMessage(id string, by string) error {
// mysql query goes here
}
I have message_id which is string and id which is primary key.
I would like to accept both types for id parameter.
I have tried like this
if (by == "id") {
int_id, err := strconv.ParseInt(id, 10, 64)
if err != nil {
panic(err)
}
id = int_id
}
But I'm getting error like
cannot use int_id (type int64) as type string in assignment
can someone help me?
Thanks
Use interface{} like this working sample:
package main
import "fmt"
import "errors"
func GetMessage(id interface{}) error {
//fmt.Printf("v:%v\tT: %[1]T \n", id)
switch v := id.(type) {
case string:
fmt.Println("Hello " + v)
case int64:
fmt.Println(v + 101)
default:
//panic("Unknown type: id.")
return errors.New("Unknown type: id.")
}
return nil
}
func main() {
message_id := "World"
id := int64(101)
GetMessage(message_id)
GetMessage(id)
}
output:
Hello World
202

Resources