I am unable to get the full data emitted from SC event by using types.Log channel. Is there any way so that I can have all the data from an event emitted?
The event I'm trying to parse:
PairCreated(address indexed,address indexed,address,uint)
My code:
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case vLog := <-logs:
fmt.Printf("Log Block Number: %d\n", vLog.BlockNumber)
fmt.Printf("Log Index: %d\n", vLog.Index)
event := make(map[string]interface{})
err := contractAbi.UnpackIntoMap(event, "PairCreated", vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Println(event)
}
}
I could only parse the last two arguments of the event.
I understood what was wrong here.
If an argument is declared as indexed that argument goes to Topics instead of Data. And there can be at most 3 topics. So, I tried to unpack the topics but failed. And succeeded with the following way:
token1 := common.HexToAddress(vLog.Topics[1].Hex())
token2 := common.HexToAddress(vLog.Topics[2].Hex())
And pair was in Data
So, the final code is:
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case vLog := <-logs:
fmt.Printf("Log Block Number: %d\n", vLog.BlockNumber)
fmt.Printf("Log Index: %d\n", vLog.Index)
event := make(map[string]interface{})
err := contractAbi.UnpackIntoMap(event, "PairCreated", vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Println(event)
token1 := common.HexToAddress(vLog.Topics[1].Hex())
token2 := common.HexToAddress(vLog.Topics[2].Hex())
}
}
Related
I'm getting values from range that I specified. But is there a way to count those values?
I'm using this method to get values from the sheets.
spreadsheetId :=""
range2 :=""
valueRenderOption := "FORMATTED_VALUE"
resp, err :=sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
Modification points:
For sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do(), when A1:C1 gives to range2, the returned value is {"majorDimension":"ROWS","range":"A1:C1","values":[["###","###","###"]]}. In this case, resp.Values is 2 dimensional array. By this, len(resp.Values) returns 1. I think that this is the reason of your issue.
When you want to retrieve the total number of cells from sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do(), how about the following modification?
Modified script:
resp, err := sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
count := 0
for _, e := range resp.Values {
count += len(e)
}
fmt.Println(count)
In this case, when A1:C1 is used for range2, 3 is returned.
Note:
For example, when you want to retrieve the total number of cells which are not empty, you can also use the following script.
resp, err := sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
count := 0
for _, e := range resp.Values {
for _, f := range e {
if f != "" {
count++
}
}
}
fmt.Println(count)
In this modified script, it supposes that you have already been able to retrieve the values from Google Spreadsheet using Sheets API. Please be careful this.
Reference:
Method: spreadsheets.values.get
I'm trying to retrieve cursor result of a PL/SQL function in golang with godror.
https://github.com/godror/godror
Using cursors returned by stored procedures
Use ExecContext and an interface{} or a database/sql/driver.Rows as the sql.Out destination, then either use the driver.Rows interface, or transform it into a regular *sql.Rows with godror.WrapRows, or (since Go 1.12) just Scan into *sql.Rows.
db, err := sql.Open("godror", "api/user#localhost/DEV")
if err != nil {
fmt.Println(err)
panic(err)
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
const query = `
DECLARE
BEGIN
:cursor := pkg_api.my_func(pstr_logn_nm => 'my_name');
END;
`
stmt, err := db.PrepareContext(ctx, query)
if err != nil {
fmt.Println(err)
panic(err)
}
var rows driver.Rows
_, err = stmt.ExecContext(ctx, sql.Out{Dest: &rows})
if err != nil {
fmt.Println(err)
}
var r []driver.Value
err = rows.Next(r)
if err != nil {
fmt.Println(err) // column count mismatch: we have 10 columns, but given 0 destination
}
defer rows.Close()
fmt.Println(rows.Columns()) // [COL_1 COL_2 COL_3 COL_4 COL_5 COL_6 COL_7 COL_8 COL_9 COL_10]
I have an error: column count mismatch: we have 10 columns, but given 0 destination
To my point of view it's because I have to define an interface with some columns.
If I try to change driver.Rows by sql.Rows I have this error:
arg: unknown type sql.Rows
If I try to create an interface I:
type I interface {
NM() string
}
var r []I
err = rows.Next(r)
I have this error: cannot use r (type []I) as type []driver.Value in argument to rows.Next
I'm also new in Golang, if someone has an idea :)
Thanks a lot!
This solved my problem!
r := make([]driver.Value, len(rows.Columns()))
err = rows.Next(r)
if err != nil {
fmt.Println(err) // column count mismatch: we have 10 columns, but given 0 destination
}
defer rows.Close()
https://github.com/godror/godror/issues/62
// SetReadLimit sets the maximum size for a message read from the peer. If a
// message exceeds the limit, the connection sends a close message to the peer
// and returns ErrReadLimit to the application.
func (c *Conn) SetReadLimit(limit int64) {
c.readLimit = limit
}
What is the unit of limit? KB? MB ?
Based on the sources of gorilla/websocket, it's in bytes.
const readLimit = 512
message := make([]byte, readLimit+1)
.....
rc.SetReadLimit(readLimit)
Here is the full unit test:
func TestReadLimit(t *testing.T) {
const readLimit = 512
message := make([]byte, readLimit+1)
var b1, b2 bytes.Buffer
wc := newConn(&fakeNetConn{Writer: &b1}, false, 1024, readLimit-2, nil, nil, nil)
rc := newTestConn(&b1, &b2, true)
rc.SetReadLimit(readLimit)
// Send message at the limit with interleaved pong.
w, _ := wc.NextWriter(BinaryMessage)
w.Write(message[:readLimit-1])
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
w.Write(message[:1])
w.Close()
// Send message larger than the limit.
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
op, _, err := rc.NextReader()
if op != BinaryMessage || err != nil {
t.Fatalf("1: NextReader() returned %d, %v", op, err)
}
op, r, err := rc.NextReader()
if op != BinaryMessage || err != nil {
t.Fatalf("2: NextReader() returned %d, %v", op, err)
}
_, err = io.Copy(ioutil.Discard, r)
if err != ErrReadLimit {
t.Fatalf("io.Copy() returned %v", err)
}
}
This does not seem to be well-documented indeed, but according to the corresponding test it is in bytes. I'd assume that to be a default unit anyway.
The relevant test code:
// Send message at the limit with interleaved pong.
w, _ := wc.NextWriter(BinaryMessage)
w.Write(message[:readLimit-1])
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
w.Write(message[:1])
w.Close()
// Send message larger than the limit.
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
// ...
_, err = io.Copy(ioutil.Discard, r)
if err != ErrReadLimit {
t.Fatalf("io.Copy() returned %v", err)
}
I have stored the last one hour data into file. So I've to upload the previous data to openTSTB.
So, the code is as follows:
go func() {
file, err := os.Open("/var/lib/agent/agent.db")
if err != nil {
fmt.Println(err, "Err")
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
arr := []byte(scanner.Text())
url := "http://192.168.2.40:4242/api/put"
req, err := http.NewRequest("POST", url, bytes.NewBuffer(arr))
req.Header.Set("Content-Type", "")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
}()
The above code pushes the last one hour data to openTSTB.
Current data is also pushed to openTSTB using another GoRoutine.
The code is as follows:
// Regular run
go func() {
timeStamp, _ := strconv.ParseInt(strconv.FormatInt(time.Now().UnixNano()/1e9, 10), 10, 64)
err := opentsdb.Put(
MetricName,
4,
timeStamp,
opentsdb.Tag{"host", hostname},
)
}()
The problem is if last record is 4, my previous record has been uploaded with the old data [Ex: 4+4].
If I run single GoRoutine, it is working correctly. If I go with old and current data, the result is wrong.
How to fix this? Any help is greatly appreciated. Thanks in advance.
I’ve written a short program in Go to communicate with a sensor through a serial port:
package main
import (
"fmt"
"github.com/tarm/goserial"
"time"
)
func main() {
c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 9600}
s, err := serial.OpenPort(c)
if err != nil {
fmt.Println(err)
}
_, err = s.Write([]byte("\x16\x02N0C0 G A\x03\x0d\x0a"))
if err != nil {
fmt.Println(err)
}
time.Sleep(time.Second/2)
buf := make([]byte, 40)
n, err := s.Read(buf)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(buf[:n]))
s.Close()
}
It works fine, but after writing to the port I have to wait about half a second before I can start reading from it. I would like to use a while-loop instead of time.Sleep to read all incoming data. My attempt doesn’t work:
buf := make([]byte, 40)
n := 0
for {
n, _ := s.Read(buf)
if n > 0 {
break
}
}
fmt.Println(string(buf[:n]))
I guess buf gets overwritten after every loop pass. Any suggestions?
Your problem is that Read() will return whenever it has some data - it won't wait for all the data. See the io.Reader specification for more info
What you want to do is read until you reach some delimiter. I don't know exactly what format you are trying to use, but it looks like maybe \x0a is the end delimiter.
In which case you would use a bufio.Reader like this
reader := bufio.NewReader(s)
reply, err := reader.ReadBytes('\x0a')
if err != nil {
panic(err)
}
fmt.Println(reply)
Which will read data until the first \x0a.
I guess buf gets overwritten after every loop pass. Any suggestions?
Yes, buf will get overwritten with every call to Read().
A timeout on the file handle would be the approach I would take.
s, _ := os.OpenFile("/dev/ttyS0", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
t := syscall.Termios{
Iflag: syscall.IGNPAR,
Cflag: syscall.CS8 | syscall.CREAD | syscall.CLOCAL | syscall.B115200,
Cc: [32]uint8{syscall.VMIN: 0, syscall.VTIME: uint8(20)}, //2.0s timeout
Ispeed: syscall.B115200,
Ospeed: syscall.B115200,
}
// syscall
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(s.Fd()),
uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&t)),
0, 0, 0)
// Send message
n, _ := s.Write([]byte("Test message"))
// Receive reply
for {
buf := make([]byte, 128)
n, err = s.Read(buf)
if err != nil { // err will equal io.EOF
break
}
fmt.Printf("%v\n", string(buf))
}
Also note, if there is no more data read and there is no error, os.File.Read() will return an error of io.EOF,
as you can see here.