uint8 to literal string representation - string

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)
}

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()
}

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

how to return struct duitonary in golang funtion

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 {
...
}

How do I save an entire string as a txt file in Go?

I'm creating a simple word processing program in Go. From the command line, I have two prompts:
$Enter Title:
$Enter Body:
The program is supposed to save the document as a txt file and print it to the command line. The program works if the user user types in a one-word Title and a one-word Body. But if the user types in a several-word title, this will happen:
$Enter Title: Here is a title
$Enter Body: s
$ title
-bash: title: command not found
Here is the code I have so far:
package main
import (
"fmt"
"io/ioutil"
)
//Create struct for a document
type Document struct {
Title string
Body []byte
}
//Save document as txt file
func (p *Document) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
//Load document
func loadPage(title string) (*Document, error) {
filename := title + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Document{Title: title, Body: body}, nil
}
//Input document title and body.
func main() {
fmt.Print("Enter Title: ")
var Title string
fmt.Scanln(&Title)
fmt.Print("Enter Body: ")
var Body []byte
fmt.Scanln(&Body)
//Save document and display on command line
p1 := &Document{Title: Title, Body: []byte(Body)}
p1.save()
p2, _ := loadPage(Title)
fmt.Println(string(p2.Body))
}
What about using bufio.ReadString instead of fmt.Scanln?
Not 100% how Scanln works, but I am pretty sure the issue comes from a misuse of that function.
Example with bufio:
package main
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
)
// Document represent the document's data.
type Document struct {
Title string
Body []byte
}
// Save dumps document as txt file on disc.
func (p *Document) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
// loadPage loads a document from disc.
func loadPage(title string) (*Document, error) {
filename := title + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Document{Title: title, Body: body}, nil
}
// Input document title and body.
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Title: ")
title, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
title = strings.TrimSpace(title)
fmt.Print("Enter Body: ")
body, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
body = strings.TrimSpace(body)
//Save document and display on command line
p1 := &Document{Title: title, Body: []byte(body)}
if err := p1.save(); err != nil {
log.Fatal(err)
}
p2, err := loadPage(title)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(p2.Body))
}

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