how to return struct duitonary in golang funtion - excel

i need to retrun struct duitonary from a funtion and when it run script i'm gettting cannot use res (type []exceldata) as type []struct {} in return argument
I have created struct in my go script and i added values to that and added to array now i need to return it to main funtion
package main
import (
"fmt"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/360EntSecGroup-Skylar/excelize"
"log"
)
type exceldata struct {
username string
rfid string
user string
}
func read() []struct{} {
exdata := exceldata{}
res := []exceldata{}
f, err := excelize.OpenFile("./required_details.xlsx")
if err != nil {
fmt.Println(err)
return res
}
// Get value from cell by given worksheet name and axis.
/*cell, err := f.GetCellValue("Sheet1", "A566")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(cell)*/
// Get all the rows in the Sheet1.
rows, err := f.GetRows("Sheet1")
for _, row := range rows {
if row[0] != "eof"{
exdata.username = row[0]
exdata.rfid = row[1]
exdata.user = row[2]
res = append(res, exdata)
fmt.Println(res)
}else{
return res
}
}
return res;
}
func main() {
fmt.Println("Go MySQL Tutorial")
resexceldata := []exceldata{}
resexceldata =read()
fmt.Println("Routes are Loded.")
}

You are already difining exceldata as a type, so you should use that type:
type exceldata struct
...
func read() []exceldata {
...
}

Related

ksuid genration return string in go

I am using below function to generate ksuid in byte format but i need it to return ksuid in string format.
I tried returning id.string() value but i am getting below error
error:
cannot use id.String() (value of type string) as id_return value in return statement.
I would like it to assign the return string value like below (string instead of byte)
var id_gen string = genKsuid()
type id []byte
type id_return string
func genKsuid() id {
id, err := ksuid.NewRandomWithTime(time.Now())
if err != nil {
log.Fatal(err)
}
fmt.Printf("ksuid: %s\n", id.String())
return id.Bytes()
}
var id_gen []byte = genKsuid()
Change your function to
func genKsuid() string {
id, err := ksuid.NewRandomWithTime(time.Now())
if err != nil {
log.Fatal(err)
}
fmt.Printf("ksuid: %s\n", id.String())
return id.String()
}

How to split string two between characters

I want to split a string up between two characters( {{ and }} ).
I have an string like {{number1}} + {{number2}} > {{number3}}
and I'm looking for something that returns:
[number1, number2, number3]
You can try it with Regex:
s := "{{number1}} + {{number2}} > {{number3}}"
// Find all substrings in form {<var name>}
re := regexp.MustCompile("{[a-z]*[0-9]*[a-z]*}")
nums := re.FindAllString(s, -1)
// Remove '{' and '}' from all substrings
for i, _ := range nums {
nums[i] = strings.TrimPrefix(nums[i], "{")
nums[i] = strings.TrimSuffix(nums[i], "}")
}
fmt.Println(nums) // output: [number1 number2 number3]
You can experiment with regex here: https://regex101.com/r/kkPWAS/1
Use the regex [A-Za-z]+[0-9] and filter the alpha numeric parts of the string as string array.
package main
import (
"fmt"
"regexp"
)
func main() {
s := `{{number1}} + {{number2}} > {{number3}}`
re := regexp.MustCompile("[A-Za-z]+[0-9]")
p := re.FindAllString(s, -1)
fmt.Println(p) //[number1 number2 number3]
}
the hard way using the template parser ^^
package main
import (
"fmt"
"strings"
"text/template/parse"
)
func main() {
input := "{{number1}} + {{number2}} > {{number3}}"
out := parseit(input)
fmt.Printf("%#v\n", out)
}
func parseit(input string) (out []string) {
input = strings.Replace(input, "{{", "{{.", -1) // Force func calls to become variables.
tree, err := parse.Parse("", input, "{{", "}}")
if err != nil {
panic(err)
}
visit(tree[""].Root, func(n parse.Node) bool {
x, ok := n.(*parse.FieldNode)
if ok {
out = append(out, strings.Join(x.Ident, "."))
}
return true
})
return
}
func visit(n parse.Node, fn func(parse.Node) bool) bool {
if n == nil {
return true
}
if !fn(n) {
return false
}
if l, ok := n.(*parse.ListNode); ok {
for _, nn := range l.Nodes {
if !visit(nn, fn) {
continue
}
}
}
if l, ok := n.(*parse.RangeNode); ok {
if !visit(l.BranchNode.Pipe, fn) {
return false
}
if l.BranchNode.List != nil {
if !visit(l.BranchNode.List, fn) {
return false
}
}
if l.BranchNode.ElseList != nil {
if !visit(l.BranchNode.ElseList, fn) {
return false
}
}
}
if l, ok := n.(*parse.ActionNode); ok {
for _, c := range l.Pipe.Decl {
if !visit(c, fn) {
continue
}
}
for _, c := range l.Pipe.Cmds {
if !visit(c, fn) {
continue
}
}
}
if l, ok := n.(*parse.CommandNode); ok {
for _, a := range l.Args {
if !visit(a, fn) {
continue
}
}
}
if l, ok := n.(*parse.PipeNode); ok {
for _, a := range l.Decl {
if !visit(a, fn) {
continue
}
}
for _, a := range l.Cmds {
if !visit(a, fn) {
continue
}
}
}
return true
}
If it happens you really were manipulating template string, but fails to do so due to function calls and that you do not want to execute this input = strings.Replace(input, "{{", "{{.", -1) // Force func calls to become variables.
You can always force load a template using functions similar to
var reMissingIdent = regexp.MustCompile(`template: :[0-9]+: function "([^"]+)" not defined`)
func ParseTextTemplateAnyway(s string) (*texttemplate.Template, texttemplate.FuncMap, error) {
fn := texttemplate.FuncMap{}
for {
t, err := texttemplate.New("").Funcs(fn).Parse(s)
if err == nil {
return t, fn, err
}
s := err.Error()
res := reMissingIdent.FindAllStringSubmatch(s, -1)
if len(res) > 0 {
fn[res[0][1]] = func(s ...interface{}) string { return "" }
} else {
return t, fn, err
}
}
// return nil, nil
}
You don't need to use libraries. You can create your own function.
package main
const r1 = '{'
const r2 = '}'
func GetStrings(in string) (out []string) {
var tren string
wr := false
f := true
for _, c := range in {
if wr && c != r2 {
tren = tren + string(c)
}
if c == r1 {
f = !f
wr = f
}
if c == r2 {
wr = false
if f {
out = append(out, tren)
tren = ""
}
f = !f
}
}
return
}

unexpected EOF with fmt.Scanner

If I want to scan through a string, I can do this:
package main
import (
"fmt"
"strings"
)
func main() {
r := strings.NewReader("west north east")
for {
var s string
_, e := fmt.Fscan(r, &s)
fmt.Printf("%q %v\n", s, e)
if e != nil { break }
}
}
Result:
"west" <nil>
"north" <nil>
"east" <nil>
"" EOF
I recently discovered fmt.Scanner [1], so I thought I would try to implement
it. I came up with this:
package main
import (
"fmt"
"strings"
)
type comma struct { tok string }
func (c *comma) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool {
return r != ','
})
if err != nil {
return err
}
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
return err
}
}
c.tok = string(tok)
return nil
}
func main() {
r := strings.NewReader("west,north,east")
for {
var c comma
_, e := fmt.Fscan(r, &c)
fmt.Printf("%q %v\n", c.tok, e)
if e != nil { break }
}
}
Result:
"west" <nil>
"north" <nil>
"east" <nil>
"" unexpected EOF
So the result is pretty close, but what bothers me is the unexpected EOF. Is
it possible to just get a regular EOF with a custom fmt.Scanner? Am I doing
something wrong here, or is this a bug?
https://golang.org/pkg/fmt#Scanner
Thanks to Ian Lance Taylor on the golang-nuts list, he suggested to panic
the error instead of return. In the Go code, Fscan calls a function
doScan, which in turn calls a function errorHandler [1]. This last function
uses recover to turn any panic into regular error. This program gives
idential output to my original example:
package main
import (
"fmt"
"strings"
)
type comma struct { tok string }
func (c *comma) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool {
return r != ','
})
if err != nil { return err }
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
c.tok = string(tok)
return nil
}
func main() {
r := strings.NewReader("west,north,east")
for {
var c comma
_, err := fmt.Fscan(r, &c)
fmt.Printf("%q %v\n", c.tok, err)
if err != nil { break }
}
}
https://github.com/golang/go/blob/go1.16.4/src/fmt/scan.go#L1056-L1067

uint8 to literal string representation

I'm trying to access the HackerNews API endpoint with a given ID 22024283 which represents a particular news item e.g https://hacker-news.firebaseio.com/v0/22024283.json
This itemID is of type uint8and I need to convert this to it's string representation to insert into the URL.
I cannot use strconv.Itoa(int(id)) as that will produce the number 91 and not preserve 22024283.
Any help on this would be appreciated. Here is my code so far, function of interest is GetHackerNewsItem():
import (
"fmt"
"io/ioutil"
"net/http"
"strconv"
"time"
)
//Client represents connection to firebase datastore
type Client struct {
BASEURI string
Version string
Suffix string
}
type Item struct {
id int `json:"id"`
itemtype string `json:"itemtype"`
by string `json:"by"`
time time.Time `json:"time"`
kids []int `json:"kids"`
url string `json:"url"`
score int `json:"score"`
text string `json:"text"`
title string `json:"title"`
descendants int `json:"descendants"`
}
//Connect to firebase datastore
func NewHackerNewsClient() *Client {
var client Client
client.BASEURI = "https://hacker-news.firebaseio.com/"
client.Version = "v0"
client.Suffix = ".json"
return &client
}
func MakeHTTPRequest(url string) ([]byte, error) {
response, err := http.Get(url)
if err != nil {
fmt.Printf("The http request failed with the error %s\n", err)
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Printf("Failed to read response data with the error %s\n", err)
return nil, err
}
return body, nil
}
func (client *Client) GetHackerNewsItem(id uint8) []byte {
itemID := strconv.Itoa(int(id))
fmt.Printf(itemID)
url := client.BASEURI + client.Version + itemID + client.Suffix
fmt.Printf(url)
item, _ := MakeHTTPRequest(url)
fmt.Print(item)
return item
}
func (client *Client) GetTopStories() {
url := client.BASEURI + client.Version + "/topstories/" + client.Suffix
itemArray, _ := MakeHTTPRequest(url)
for i := 0; i < len(itemArray); i++ {
item := client.GetHackerNewsItem(itemArray[i])
fmt.Print(item)
}
}
func main() {
client := NewHackerNewsClient()
client.GetTopStories()
}
itemArray, _ := MakeHTTPRequest(url)
itemArray must be unmarshaled like
dat := make([]uint64, 0)
if err := json.Unmarshal(itemArray, &dat); err != nil {
panic(err)
}

Reading from reader until a string is reached

I am trying to write a function to keep reading from a buffered reader until I hit a certain string, then to stop reading and return everything read prior to that string.
In other words, I want to do the same thing as reader.ReadString() does, except taking a string instead of a single byte.
For instance:
mydata, err := reader.ReadString("\r\n.\r\n") //obviously will not compile
How can I do this?
Thanks in advance,
Twichy
Amendment 1: Previous attempt
Here is my previous attempt; its badly written and doesnt work but hopefully it demonstrates what I am trying to do.
func readDotData(reader *bufio.Reader)(string, error){
delims := []byte{ '\r', '\n', '.', '\r', '\n'}
curpos := 0
var buffer []byte
for {
curpos = 0
data, err := reader.ReadSlice(delims[0])
if err!=nil{ return "", err }
buffer = append(buffer, data...)
for {
curpos++
b, err := reader.ReadByte()
if err!=nil{ return "", err }
if b!=delims[curpos]{
for curpos >= 0{
buffer = append(buffer, delims[curpos])
curpos--
}
break
}
if curpos == len(delims){
return string(buffer[len(buffer)-1:]), nil
}
}
}
panic("unreachable")
}
package main
import (
"bytes"
"fmt"
"log"
)
type reader interface {
ReadString(delim byte) (line string, err error)
}
func read(r reader, delim []byte) (line []byte, err error) {
for {
s := ""
s, err = r.ReadString(delim[len(delim)-1])
if err != nil {
return
}
line = append(line, []byte(s)...)
if bytes.HasSuffix(line, delim) {
return line[:len(line)-len(delim)], nil
}
}
}
func main() {
src := bytes.NewBufferString("123deli456elim789delimABCdelimDEF")
for {
b, err := read(src, []byte("delim"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q\n", b)
}
}
Playground
Output:
"123deli456elim789"
"ABC"
2009/11/10 23:00:00 EOF
http://play.golang.org/p/BpA5pOc-Rn
package main
import (
"bytes"
"fmt"
)
func main() {
b := bytes.NewBuffer([]byte("Hello, playground!\r\n.\r\nIrrelevant trailer."))
c := make([]byte, 0, b.Len())
for {
p := b.Bytes()
if bytes.Equal(p[:5], []byte("\r\n.\r\n")) {
fmt.Println(string(c))
return
}
c = append(c, b.Next(1)...)
}
}
For example,
package main
import (
"bufio"
"bytes"
"fmt"
"strings"
)
var delim = []byte{'\r', '\n', '.', '\r', '\n'}
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
for i := 0; i+len(delim) <= len(data); {
j := i + bytes.IndexByte(data[i:], delim[0])
if j < i {
break
}
if bytes.Equal(data[j+1:j+len(delim)], delim[1:]) {
// We have a full delim-terminated line.
return j + len(delim), data[0:j], nil
}
i = j + 1
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}
// Request more data.
return 0, nil, nil
}
func main() {
delims := string(delim)
input := "1234" + delims + "5678" + delims + "1234567901234567890" + delims
scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(ScanLines)
for scanner.Scan() {
fmt.Printf("%s\n", scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Printf("Invalid input: %s", err)
}
}
Output:
1234
5678
1234567901234567890
Because you have the same byte in the string, you can do it as below:
func readWithEnd(reader *bufio.Reader) ([]byte, error) {
message, err := reader.ReadBytes('#')
if err != nil {
return nil, err
}
a1, err := reader.ReadByte()
if err != nil {
return nil, err
}
message = append(message, a1)
if a1 != '\t' {
message2, err := readWithEnd(reader)
if err != nil {
return nil, err
}
ret := append(message, message2...)
return ret, nil
}
a2, err := reader.ReadByte()
if err != nil {
return nil, err
}
message = append(message, a2)
if a2 != '#' {
message2, err := readWithEnd(reader)
if err != nil {
return nil, err
}
ret := append(message, message2...)
return ret, nil
}
return message, nil
}
This is the sample that can recognize the "#\t#" in TCP connection

Resources