Load file metadata with go - metadata

Does anyone know of a way to read the metadata and or properties of a file using the go language?

package main
import (
"fmt"
"os"
)
func main() {
fi, err := os.Stat("filename")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(fi.Name(), fi.Size())
}

Use below code, please change your path at place "filename or entire path".
package main
import (
"fmt"
"os"
)
func main() {
//The file has to be opened first
f, err := os.Open("filename or entire path")
// The file descriptor (File*) has to be used to get metadata
fi, err := f.Stat()
// The file can be closed
f.Close()
if err != nil {
fmt.Println(err)
return
}
// fi is a fileInfo interface returned by Stat
fmt.Println(fi.Name(), fi.Size())
}

Related

the Insert operation must have a Deployment set before Execute can be called

I have an AWS instance with MongoDB running. I am trying to do a small db operation which seems to work when the files included below was written inside a single go file. When I try to split it I get the following error
the Insert operation must have a Deployment set before Execute can be called
The split files are given below
connect.go
package db
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var Client1 mongo.Client
func Connect() {
// Set client options
clientOptions := options.Client().ApplyURI("remote_url")
// Connect to MongoDB
Client1, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
// Check the connection
err = Client1.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
}
func main() {
fmt.Println("Connection to MongoDB done.")
}
main.go
package main
import (
"context"
"fmt"
"log"
"db"
"go.mongodb.org/mongo-driver/bson"
)
// You will be using this Trainer type later in the program
type Trainer struct {
Name string
Age int
City string
}
func main() {
db.Connect()
collection := db.Client1.Database("test2").Collection("trainers")
_ = collection
fmt.Println("Created collection", _)
ash := Trainer{"Ash", 10, "Pallet Town"}
// misty := Trainer{"Misty", 10, "Cerulean City"}
// brock := Trainer{"Brock", 15, "Pewter City"}
insertResult, err := collection.InsertOne(context.TODO(), ash)
if err != nil {
log.Fatal(err)
}
fmt.Println("Inserted a single document: ", insertResult)
err = db.Client1.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")
}
They are placed in the following structure
/src -> main.go
/src -> /db/connect.go
I believe that your problem is caused by variable shadowing (wiki) and you're initializing a local variable and not the global mongo.Client object, hence throwing the error that you're getting.
It happens in your connect.go file, where you have defined two different Client1 variables with the same name:
One at global scope
Another in Connect() that gets declared+initialised when calling mongo.Connect()
var Client1 mongo.Client // Client1 at global scope
func Connect() {
// Set client options
clientOptions := options.Client().ApplyURI("remote_url")
// Connect to MongoDB
Client1, err := mongo.Connect(context.TODO(), clientOptions) // Client1 at local scope within Connect()
That causes that the one at global scope is never initialised so main.go crashes when trying to use it because it's nil.
There are several ways to solve this, for example by using a different name for the variable at local scope and assign the client to the global one:
var Client1 mongo.Client
func Connect() {
// Set client options
clientOptions := options.Client().ApplyURI("remote_url")
// Connect to MongoDB
Client1Local, err := mongo.Connect(context.TODO(), clientOptions)
Client1 = *Client1Local
Or avoid declaring the local variable and directly initialise the one at global scope:
var Client1 *mongo.Client // Note that now Client1 is of *mongo.Client type
func Connect() {
// Set client options
clientOptions := options.Client().ApplyURI("remote_url")
// Connect to MongoDB
var err error
Client1, err = mongo.Connect(context.TODO(), clientOptions) // Now it's an assignment, not a declaration+assignment anymore
More about Golang's variable shadowing discussion at Issue#377 proposal
Try to include like, since the you have omitted the db directory , that might have be the issue
import "db/db"
Also there is main() in connect.go there should be only one main package and main() function for a project.
---------------- Try what is discussed below exactly ------------
Ok this is my test setup with directory tree of code similar to yours:
[user#devsetup src]$ tree test
test
├── dbtest
│   └── db
│   └── connect.go
├── main // This is executable file
└── main.go
2 directories, 3 files
In connect.go i havent changed anything but removed the main() as mentioned above.
Make sure you use only exported functions and variables , Exported functions/Variables starts with Capital letter.
In main.go looks like the code below.
* Go to dbtest/db directory and run go install command. then go the project directory , ie test here in this case, and run go build main.go or go build .
package main
import (
"context"
"fmt"
"log"
"test/dbtest/db"
// "go.mongodb.org/mongo-driver/bson"
)
// You will be using this Trainer type later in the program
type Trainer struct {
Name string
Age int
City string
}
func main() {
db.Connect()
collection := db.Client1.Database("test2").Collection("trainers")
_ = collection
// fmt.Println("Created collection", _)
ash := Trainer{"Ash", 10, "Pallet Town"}
// misty := Trainer{"Misty", 10, "Cerulean City"}
// brock := Trainer{"Brock", 15, "Pewter City"}
insertResult, err := collection.InsertOne(context.TODO(), ash)
if err != nil {
log.Fatal(err)
}
fmt.Println("Inserted a single document: ", insertResult)
err = db.Client1.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")
}
This is my binary output since i havent given any input url , it is throwing an error.Seems working. I have commented out a package and a line in main.go
[user#devsetup test]$ ./test
20xx/yy/zz aa:bb:cc error parsing uri: scheme must be "mongodb" or "mongodb+srv"

Using os.OpenFile() instead of net.Listen()

I've dived into the call stack of both os.OpenFile and net.Listen to see if I can make a UNIX domain socket using os.OpenFile. Below is my attempt. But, after tracing both call stacks (os.OpenFile's and net.Listen's) I'm still confused. The below code doesn't read from the file, apparently, and stores the data to the filesystem.
How can I implement a UNIX domain socket using os.OpenFile?
What is the purpose of os.ModeSocket if it's not to be used with os.OpenFile to create a UNIX socket?
package main
import (
"fmt"
"log"
"os"
)
func main() {
sock, err := os.OpenFile("f.sock", os.O_RDWR|os.O_CREATE, os.ModeSocket|os.ModePerm)
defer sock.Close()
if err != nil {
log.Panic(err)
}
n, err := sock.WriteString("hello\n")
if err != nil {
fmt.Println(err)
} else {
fmt.Println(n)
}
b := make([]byte, 10)
n, err = sock.Read(b)
fmt.Println(n)
if err != nil {
fmt.Println("error reading: ", err)
}
fmt.Println(b)
}
No. OpenFile is a generalized api for opening file, use net.Listen("unixpacket", "f.sock") or net.Dial("unixpacket", "f.sock") if you wanna work with unix socket
os.ModeSocket is just a *nix registered flag for socket fd, use when you want to filter fd types

How do you parse date in the format:

It's not clear to me from the documentation how I would parse a date in this somewhat strange format. It seems like it might not be possible.
2016-07-08T08:34:24+00:00
The following does not work (go play link)
package main
import (
"fmt"
"time"
)
func main() {
date := "2016-07-08T08:34:24+00:00"
d, err := time.Parse("2006-01-02T15:04:05+07:00", date)
if err == nil {
fmt.Println(d)
} else {
fmt.Println(err)
}
}
Obviously a regexp could first check for this format and transform the + to a -, but that implies the standard library cant parse this date.
Go's reference layout uses -7 hours as the timezone offset, but you used +7 hours:
package main
import (
"fmt"
"time"
)
func main() {
date := "2016-07-08T08:34:24+00:00"
d, err := time.Parse("2006-01-02T15:04:05-07:00", date)
if err == nil {
fmt.Println(d)
} else {
fmt.Println(err)
}
}
https://play.golang.org/p/FNzx57R2jy

How to run a CLI command from Go?

How do I run a Gulp task from a Go program?
This is the command I run from a typical terminal:
gulp serv.dev
How could I run this simple line of code from golang:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
)
func main() {
// What do I put here to open terminal in background and run `gulp serv.dev`?
}
What you're looking for is exec.Command
You'll pretty much want to spawn off a process that will run your gulp task.
This can be done like so:
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("gulp", "serv.dev")
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
Take a look at exec. For your use case:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
"os/exec"
"log"
)
func main() {
out, err := exec.Command("gulp", "serv.dev").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
Most probably you need exec package
cmd := exec.Command("gulp", "serv.dev")
err := cmd.Run()
Take a look at example at exec.Command. They explained how to pass parameters and read the output.
More generic, better output.
Use the exec.Command, along with buffers to record output and display it only when useful.
You can even make the function work with any command by using variadic arguments, aka arguments of an arbitrary quantity of elements.
Label unhanded errors appropriately, so if a command fails you are told which one and why.
Lastly note that Go, although expressive, is a quite raw language. It holds your hand for nothing. You will have to program plenty by yourself.
Example code:
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
)
func main() {
runCommand(currentFunction(), "ping", "-c1", "google.commm")
}
func commandErrorMessage(stderr bytes.Buffer, program string) string {
message := string(stderr.Bytes())
if len(message) == 0 {
message = "the command doesn't exist: " + program + "\n"
}
return message
}
func currentFunction() string {
counter, _, _, success := runtime.Caller(1)
if !success {
println("functionName: runtime.Caller: failed")
os.Exit(1)
}
return runtime.FuncForPC(counter).Name()
}
func printCommandError(stderr bytes.Buffer, callerFunc string, program string, args ...string) {
printCommandErrorUbication(callerFunc, program, args...)
fmt.Fprintf(os.Stderr, "%s", commandErrorMessage(stderr, program))
}
func printCommandErrorUbication(callerFunc string, program string, args ...string) {
format := "error at: %s: %s %s\n"
argsJoined := strings.Join(args, " ")
fmt.Fprintf(os.Stderr, format, callerFunc, program, argsJoined)
}
func runCommand(callerFunc string, program string, args ...string) {
command := exec.Command(program, args...)
var stderr bytes.Buffer
command.Stderr = &stderr
fail := command.Run()
if fail != nil {
printCommandError(stderr, callerFunc, program, args...)
os.Exit(1)
}
}
Example run:
$ go run test.go
error at: main.main: ping -c1 google.commm
ping: google.commm: Name or service not known
exit status 1

Go: Variable from PostgreSQL in template not output value (Echo framework)

Many codes taken from Martini example, but this using Echo framework.
I can make it works in Martini but not in Echo.
server.go:
package main
import (
"database/sql"
"github.com/labstack/echo"
_ "github.com/lib/pq"
"html/template"
"io"
"log"
"net/http"
)
type Book struct {
Title, Author, Description string
}
type (
Template struct {
templates *template.Template
}
)
func (t *Template) Render(w io.Writer, name string, data interface{}) error {
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
db, err := sql.Open("postgres", "user=postgres password=apassword dbname=lesson4 sslmode=disable")
if err != nil {
log.Fatal(err)
}
t := &Template{
templates: template.Must(template.ParseFiles("public/views/testhere.html")),
}
e.Renderer(t)
e.Get("/post/:idnumber", func(c *echo.Context) {
rows, err := db.Query("SELECT title, author, description FROM books WHERE id=$1", c.Param("idnumber"))
if err != nil {
log.Fatal(err)
}
books := []Book{}
for rows.Next() {
b := Book{}
err := rows.Scan(&b.Title, &b.Author, &b.Description)
if err != nil {
log.Fatal(err)
}
books = append(books, b)
}
c.Render(http.StatusOK, "onlytestingtpl", books)
})
e.Run(":4444")
}
public/views/testhere.html:
{{define "onlytestingtpl"}}Book title is {{.Title}}. Written by {{.Author}}. The book is about {{.Description}}.{{end}}
I cannot figure out since no error message, and no SQL documentation of this framework. When running, it gives:
Book title is
(The variable not output value)
As I mentioned in a comment, you shouldn't execute a template that takes a struct with a slice of structs. Either use {{range}} in your template, or do
c.Render(http.StatusOK, "onlytestingtpl", books[0])