Binance Websocket API aggTrade Stream always gives "m" parameter true - go

I want to get binance aggtrade data from websocket and this is their documentation (https://binance-docs.github.io/apidocs/spot/en/#live-subscribing-unsubscribing-to-streams). In this documentation there is a "m" parameter which describes trade is buy or sell. But this parameter is always true when I am getting data.
I am coding in Go and here is my code for getting data with websocket.
package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
)
type AggTrade struct {
S string `json:"s"`
P string `json:"p"`
M bool `json:"m"`
E int64 `json:"E"`
}
func main() {
conn, res, err := websocket.DefaultDialer.Dial("wss://stream.binance.com:9443/ws/btcusdt#aggTrade", nil)
fmt.Println(conn)
fmt.Println(res)
fmt.Println(err)
var aggTrade AggTrade
for {
_, message, readErr := conn.ReadMessage()
if readErr != nil {
fmt.Println(readErr)
return
}
json.Unmarshal(message, &aggTrade)
fmt.Println(aggTrade)
}
}
Is there a change that I am not aware of? This "m" parameter is always true

Related

How do I get two integer values ​from the client by the terminal in this code - GO RPC

RPC Client Server with GO
Guys, how do I get two integer values ​​from the client by the terminal in this code, in arg A and B ? I need to make an account on the server and return it, but I don't understand go
SERVER
package main
import (
"log"
"net"
"net/http"
"net/rpc"
)
type Args struct{A,B int}
type BannerMessageServer string
func (t *BannerMessageServer) GetBannerMessage(args *Args, reply *string) error {
*reply = "Sever OK"
return nil
}
func main() {
banner := new(BannerMessageServer)
rpc.Register(banner)
rpc.HandleHTTP()
port := ":1122"
listener, err := net.Listen("tcp", port)
if err != nil {
log.Fatal("listen error: ", err)
}
http.Serve(listener, nil)
}
CLIENT
package main
import (
"log"
"net/rpc"
)
type Args struct{
A, B int
}
func main() {
hostname := "localhost"
port := ":1122"
var reply string
args := Args{A,B}
client, err := rpc.DialHTTP("tcp", hostname+port)
if err != nil {
log.Fatal("dialing: ", err)
}
err = client.Call("BannerMessageServer.GetBannerMessage", args, &reply)
if err != nil {
log.Fatal("error", err)
}
// log the result
log.Printf("%s\n", reply)
}
It's an rpc client server, I want to receive two values ​​to do mathematical calculation and return
Can anyone help? need more details, just ask

Semantic way of http.Response receiver functions in Go

I just started learning GO and wrote this piece of code that writes an http.Response.Body to os.Stdout or to a file, but I'm not happy about the semantics of this.
I want the http.Response struct to have these receiver functions, so I can use it more easily throughout the entire app.
I know that the answers might get flagged as opinionated, but I still wonder, is there a better way of writing this?
Is there some sort of best practice?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
)
type httpResp http.Response
func main() {
res, err := http.Get("http://www.stackoverflow.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
response := httpResp(*res)
response.toFile("stckovrflw.html")
response.toStdOut()
}
func (r httpResp) toFile(filename string) {
str, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
ioutil.WriteFile(filename, []byte(str), 0666)
}
func (r httpResp) toStdOut() {
_, err := io.Copy(os.Stdout, r.Body)
if err != nil {
panic(err)
}
}
On a side note, is there a way to make the http.Get method spit out a custom type that already has access to these receiver functions without the need for casting? So i could do something like this:
func main() {
res, err := http.Get("http://www.stackoverflow.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
res.toFile("stckovrflw.html")
res.toStdOut()
}
Thanks!
You don't have to implement these functions. *http.Response already implements io.Writer:
Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer.
package main
import (
"net/http"
"os"
)
func main() {
r := &http.Response{}
r.Write(os.Stdout)
}
In the example above, the zero value prints:
HTTP/0.0 000 status code 0
Content-Length: 0
Playground: https://play.golang.org/p/2AUEAUPCA8j
In case you need additional business logic in the write methods, you can embed *http.Response in your defined type:
type RespWrapper struct {
*http.Response
}
func (w *RespWrapper) toStdOut() {
_, err := io.Copy(os.Stdout, w.Body)
if err != nil {
panic(err)
}
}
But then you must construct a variable of type RespWrapper with the *http.Response:
func main() {
// resp with a fake body
r := &http.Response{Body: io.NopCloser(strings.NewReader("foo"))}
// or r, _ := http.Get("example.com")
// construct the wrapper
wrapper := &RespWrapper{Response: r}
wrapper.toStdOut()
}
is there a way to make the http.Get method spit out a custom type
No, the return types of http.Get are (resp *http.Response, err error), that's part of the function signature, you can't change it.

Extract filename from io.ReadCloser

I need to get the filename of certain file(s) that receives backend from the frontend. Backend (implemented in Go) will receive the file as io.ReadCloser. Is there way I could extract it from the io.ReadCloser?
Backend (implemented in Go) will receive the file as io.ReadCloser. Is there way I could extract it from the io.ReadCloser?
No.
Take a look at which methods an io.ReadCloser provides by running go doc io.ReadCloser and note that there isn't a method which will provide a name. So unless you know nothing more that that it is an io.ReadCloser you simply cannot do it.
package main
import (
"errors"
"fmt"
"io"
"os"
)
func fatalln(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// hasName interface is an interface that expects types
// that implements it to have "Name() string" method.
type hasName interface {
Name() string
}
func open(name string) (io.ReadCloser, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
// f implements io.ReadCloser interface as *os.File
// has Read and Close methods.
return f, nil
}
func main() {
// rc is of the type io.ReadCloser
rc, err := open("example.txt")
if err != nil {
fatalln(err)
}
defer rc.Close()
// Type assetion to check rc's underlying type has
// a method "Name() string".
f, ok := rc.(hasName)
if !ok {
fatalln(errors.New("type assertion failed"))
}
// Yay, type assertion succeeded. Print the name!
fmt.Println("Name:", f.Name())
}
The io.ReadCloser here is a reader for runtime reader which reads file from network as the frontend sends it to backend. You'll have to work on request itself to get that file name.
This is an assumption but in most such cases for file upload, the request is a multipart request. If you have the same situation, you can read the headers, typically Content-Disposition to identify the file type. Go native http.Request has ability to parse the details. You can try this :
formFile, handler, err := r.FormFile("file") // read file from network with key "file"
defer formFile.Close()
fileName := handler.Filename // Get file name
By defining an interface which embeds io.Reader you can require a Name() method up front:
package main
import (
"fmt"
"io"
"log"
"os"
)
type NamedReadCloser interface {
io.ReadCloser
Name() string
}
func doThings(f NamedReadCloser) error {
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return err
}
fmt.Printf("Name: %s, Content: %s\n", f.Name(), b)
return nil
}
func main() {
f, err := os.Open("/etc/hosts")
if err != nil {
log.Fatal("Cannot open file: ", err)
}
err = doThings(f)
if err != nil {
log.Fatal("Error doing things: ", err)
}
}
This will only work if what is passed in has a name method, like an *os.File. If it does not, then what you are trying to do is not possible.
You'll have to cast it to a type with a Name method:
package main
import (
"io"
"os"
)
func open(name string) (io.ReadCloser, error) {
return os.Open(name)
}
func main() {
c, e := open("file.txt")
if e != nil {
panic(e)
}
defer c.Close()
f := c.(*os.File)
println(f.Name())
}

Bug in decoding an rpc reply using gob

Problem: structure's field is not replaced with fresh value if it is zero after an rpc call.
Here is minimal code sample:
package main
import (
"fmt"
"log"
"net"
"net/rpc"
)
type RpcObject int
type Reply struct {
A int
}
func (*RpcObject) GetSlice(req int, reply *[]Reply) error {
*reply = []Reply{{0}, {158}}
return nil
}
func Serve() {
addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:12345")
if err != nil {
log.Fatal(err)
}
inbound, err := net.ListenTCP("tcp", addr)
if err != nil {
log.Fatal(err)
}
handler := new(RpcObject)
rpc.Register(handler)
rpc.Accept(inbound)
}
func main() {
go Serve()
var err error
var client *rpc.Client
for client, err = rpc.Dial("tcp", "localhost:12345"); err != nil; client, err = rpc.Dial("tcp", "localhost:12345") {
fmt.Println("connecting...")
}
reply := []Reply{{225}, {9946}}
client.Call("RpcObject.GetSlice", 0, &reply)
fmt.Println(reply)
}
Output:
[{225} {158}]
I assume it is a problem with gob format, however I am not sure. Does someone know how to fix this?
The application produced the expected results. The gob encoder does not transmit the first element in the reply slice because the element is the zero value. The decoder does not set the first element in main's reply slice because a value was not received for that element.
Decode to a zero value if you do not want to set defaults for values missing from the reply:
...
var reply []Reply
client.Call("RpcObject.GetSlice", 0, &reply)
...

Passing Data from Datastore to http.Writer

I was recently introduced to the wonders of the language known as go. I set myself a task of writing a RESTful API using GoLang and Google's Datastore. I am able to retrieve data from Datastore and Print it to the console using fmt.Println however the issue comes into play when I try to use the data from Datastore and pass it to the http.Handler.
I was wondering if someone could inform me of where I am going wrong or even point me in the right direction.
Here is what I have done so far
package main
import (
"log"
"fmt"
"context"
"net/http"
// "encoding/json"
"cloud.google.com/go/datastore"
)
type Item struct {
Id string `datastore:"id"`
Name string `datastore:"title"`
View int `datastore:"views"`
Brand string `datastore:"brand"`
id int64 // interger from "Name/ID" fild in datastore entities list
}
func main() {
http.HandleFunc("/", ListTasks)
http.ListenAndServe(":8080", nil)
}
//func ListTasks(w http.ResponseWriter, r *http.Request) ([]*Item, error) {
func ListTasks(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
client, err := datastore.NewClient(ctx, "my-client")
if err != nil {
log.Fatalln(err)
}
var tasks []*Item
query := datastore.NewQuery("my-query")
keys, err := client.GetAll(ctx, query, &tasks)
if err != nil {
return nil, err
}
for i, key := range keys {
tasks[i].id = key.ID
}
return tasks, nil
}
I've also looked into http Wrappers, but I'm unaware if using a wrapper is 100% necessary or if I'm just adding more to my plate.
I've removed the return tasks, nil as it appeared to be unnecessary, modified the return, nil err to log.Fatalln(nil, err) and also encoded tasks as instructed by #ThunderCat and #tkausl. My issue has been resolved, thank you.
Here is my working code
package main
import (
"log"
"context"
"net/http"
"encoding/json"
"cloud.google.com/go/datastore"
)
type Item struct {
Id string `datastore:"id"`
Name string `datastore:"title"`
View int `datastore:"views"`
Brand string `datastore:"brand"`
id int64 // interger from "Name/ID" fild in datastore entities list
}
func main() {
http.HandleFunc("/", ListTasks)
http.ListenAndServe(":8080", nil)
}
func ListTasks(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
ctx := context.Background()
client, err := datastore.NewClient(ctx, "my-client")
if err != nil {
log.Fatalln(err)
}
var tasks []*Item
query := datastore.NewQuery("my-query")
keys, err := client.GetAll(ctx, query, &tasks)
if err != nil {
log.Fatalln(nil, err)
}
for i, key := range keys {
tasks[i].id = key.ID
}
json.NewEncoder(w).Encode(tasks)
// return tasks, nil
}
It now returns [{"Id":"24X660","Name":"Fiesta","View":129,"Brand":"Ford"}]
Also thank you to #static_cast for correcting my formatting errors.

Resources