Generate .pb file without using protoc in golang - go

I'm trying to generate .pb.go file using service.proto as file input in Go.
Is there a way to do it without using protoc binary (like directly using package github.com/golang/protobuf/protoc-gen-go)?

If you have a detail.proto like this:
message AppDetails {
optional string version = 4;
}
You can parse it into a message like this:
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/jhump/protoreflect/desc/protoparse"
"github.com/jhump/protoreflect/dynamic"
)
func parse(file, msg string) (*dynamic.Message, error) {
var p protoparse.Parser
fd, err := p.ParseFiles(file)
if err != nil {
return nil, err
}
md := fd[0].FindMessage(msg)
return dynamic.NewMessage(md), nil
}
func main() {
b := []byte("\"\vhello world")
m, err := parse("detail.proto", "AppDetails")
if err != nil {
panic(err)
}
if err := proto.Unmarshal(b, m); err != nil {
panic(err)
}
fmt.Println(m) // version:"hello world"
}
However you may notice, this package is still using the old Protobuf V1. I did
find a Pull Request for V2:
https://github.com/jhump/protoreflect/pull/354

Related

Can't find a public file from url in go

I am trying to get the content of a publicly available file using ioutil.ReadFile() but it doesn't find the file: panic: open http://www.pdf995.com/samples/pdf.pdf: No such file or directory
Here's my code:
// Reading and writing files are basic tasks needed for
// many Go programs. First we'll look at some examples of
// reading files.
package main
import (
"fmt"
"io/ioutil"
)
// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
fileInUrl, err := ioutil.ReadFile("http://www.pdf995.com/samples/pdf.pdf")
if err != nil {
panic(err)
}
fmt.Printf("HERE --- fileInUrl: %+v", fileInUrl)
}
Here's a go playground example
ioutil.ReadFile() does not support http.
If you look at the source code(https://golang.org/src/io/ioutil/ioutil.go?s=1503:1549#L42), open the file using os.Open.
I think I can do this coding.
package main
import (
"io"
"net/http"
"os"
)
func main() {
fileUrl := "http://www.pdf995.com/samples/pdf.pdf"
if err := DownloadFile("example.pdf", fileUrl); err != nil {
panic(err)
}
}
func DownloadFile(filepath string, url string) error {
// Get the data
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Write the body to file
_, err = io.Copy(out, resp.Body)
return err
}
but, go playgound not protocol(go error dial tcp: Protocol not available).
so, You have to do it PC.

os.Create and os.Open not working with gomobile and react native

package component
import (
"encoding/json"
"io/ioutil"
"os"
)
type LastComponent struct {
Name string
}
const fname = "componentfiles"
func Persist(comp string) string {
lcomp := LastComponent{Name: comp}
b, err := json.Marshal(lcomp)
if err != nil {
return "err-MARSHAL"
}
file, err := os.Create(fname)
if err != nil {
return "err-CREATE-FILE"
}
defer file.Close()
_, err = file.Write(b)
if err != nil {
return "err-FILE-WRITE-PROB"
}
return ""
}
func Component() string {
f, err := os.Open(fname)
if err != nil {
return "err-FILE-NOT-OPEN"
}
defer f.Close()
b, err := ioutil.ReadAll(f)
if err != nil {
return ""
}
var v LastComponent
json.Unmarshal(b, v)
return v.Name
}
}
The code above works fine and so does the javascript side of code. I keep receiving err-CREATE-FILE inside my javascript. So os.Create and os.Open are not working as expected.
Although it is an internal storage, permissions are not required, but I also turned on the permissions in manifest file, but with no avail.
What could be the correct way to Open and Create files in android using gomobile when using along side React Native?
Update:
In adb logcat, I keep getting this all over the place
E/Vold ( 276): Failed to find mounted volume for /storage/sdcard1/Android/data/com.gotest/cache/
So you should have some success if you pass this in as a parameter - something like the following is working for me:
go:
func Component(folderPath string) string {
f, err := os.Open(path.Join(folderPath, fname))
...
Java:
Component.Component(getApplicationContext().getFilesDir().getAbsolutePath())
Alternatively, you could use something like getExternalStorageDirectory().getAbsolutePath(). They key is that you need to get somewhere storagewise that is writable by your process/user.

Execute template to file

I have a template file template.html as follow
Hello {{.Name}}, welcome!
and the code
import (
"fmt"
"text/template"
)
func main() {
type person struct {
Name string
}
p := &person{"clinyong"}
t := template.Must(template.New("template.html").ParseFiles("template.html"))
f, err := os.OpenFile("test", os.O_CREATE, 0777)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
err := t.Execute(f, p)
if err != nil {
fmt.Println(err)
}
}
t.Execute(f, p) calls a error, saying that f is a bad file descriptor.
Is it possible to execute a template output to a file as shown above? I see some examples, the f in Execute is almost http.ResponseWriter or os.Stdout.
As #TimCooper said, I need to include os.O_WRONLY in os.OpenFile.

Is it possible to extract a tar.xz package in golang?

Is it possible to extract a tar.xz package in golang? My understanding is it's possible to use the library for tar and sending it to an xz go library.
I recently created an XZ decompression package so it is now
possible to extract a tar.xz using only Go code.
The following code extracts the file myfile.tar.xz to the current
directory:
package main
import (
"archive/tar"
"fmt"
"io"
"log"
"os"
"github.com/xi2/xz"
)
func main() {
// Open a file
f, err := os.Open("myfile.tar.xz")
if err != nil {
log.Fatal(err)
}
// Create an xz Reader
r, err := xz.NewReader(f, 0)
if err != nil {
log.Fatal(err)
}
// Create a tar Reader
tr := tar.NewReader(r)
// Iterate through the files in the archive.
for {
hdr, err := tr.Next()
if err == io.EOF {
// end of tar archive
break
}
if err != nil {
log.Fatal(err)
}
switch hdr.Typeflag {
case tar.TypeDir:
// create a directory
fmt.Println("creating: " + hdr.Name)
err = os.MkdirAll(hdr.Name, 0777)
if err != nil {
log.Fatal(err)
}
case tar.TypeReg, tar.TypeRegA:
// write a file
fmt.Println("extracting: " + hdr.Name)
w, err := os.Create(hdr.Name)
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(w, tr)
if err != nil {
log.Fatal(err)
}
w.Close()
}
}
f.Close()
}
http://golang.org/pkg/archive/tar/#example_
also you can do
import "os/exec"
cmd := exec.Command("tar", "-x", "/your/archive.tar.xz")
err := cmd.Run()
There is no Lempel-Ziv-Markow encoder or decoder in the Go standard library. If you are allowed to assume that the platform your code runs on provides the xz utility, you could use stub functions like these:
import "os/exec"
// decompress xz compressed data stream r.
func UnxzReader(r io.Reader) (io.ReadCloser, error) {
unxz := exec.Command("xz", "-d")
unxz.Stdin = r
out, err := unxz.StdoutPipe()
if err != nil {
return nil, err
}
err = unxz.Start()
if err != nil {
return nil, err
}
// we are not interested in the exit status, but we should really collect
// that zombie process
go unxz.Wait()
return out, nil
}

Decode JSON to map[string]map[string]string

I have a map[string]map[string]string that I'd like to be able to convert to JSON and write to a file, and be able to read the data back in from the file.
I've been able to successfully write to the file using the following:
func (l *Locker) Save(filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
// l.data is of type map[string]map[string]string
return encoder.Encode(l.data)
}
I'm having trouble loading the JSON back into the map. I've tried the following:
func (l *Locker) Load(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
decoder := json.NewDecoder(file)
return decoder.Decode(l.data)
}
loading a JSON file with contents {"bar":{"hello":"world"},"foo":{"bar":"new","baz":"extra"}}, and after the above the contents of l.data is just map[]. How can I successfully decode this JSON into l.data?
If you use json.Unmarshal() instead you can pass it a data structure to populate. Here's a link to the code below, in the playground.
package main
import (
"fmt"
"encoding/json"
)
func main() {
src_json := []byte(`{"bar":{"hello":"world"},"foo":{"bar":"new","baz":"extra"}}`)
d := map[string]map[string]string{}
_ = json.Unmarshal(src_json, &d)
// Print out structure
for k, v := range d {
fmt.Printf("%s\n", k)
for k2, v2 := range v {
fmt.Printf("\t%s: %s\n", k2, v2)
}
}
fmt.Println("Hello, playground")
}

Resources