Creating a presigned URL I've created software in Go to create a presigned URL:

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/minio/minio-go"
    "github.com/kelseyhightower/envconfig"
)

type AWS struct {
  Endpoint          string
  Access_Key_Id     string
  Secret_Access_Key string
  SSL               bool
  Bucket            string
  Bucket_Key        string
  Bucket_Expiry     string
}

func main() {
    var aws AWS
    // Add configurations from environment variable
    // e.g:
    //    AWS_ENDPOINT         -&gt; aws.Endpoint
    //    AWS_ACCESS_KEY_ID    -&gt; aws.Access_Key_Id
    //    ...
    if err := envconfig.Process("aws", &amp;aws); err != nil {
        log.Fatal(err.Error())
    }

    svc, err := minio.New(aws.Endpoint, aws.Access_Key_Id, aws.Secret_Access_Key, aws.SSL)
    if err != nil {
    }

    fmt.Println(aws)
    url, err := svc.PresignedPutObject(aws.Bucket, aws.Bucket_Key, aws.Bucket_Expiry)

    if err != nil {
        log.Fatalln(err)
    }

    fmt.Println("Successfully generated presigned URL", url)
}


I would like to know if it is possible to avoid all the if statements for error validations. This is my second program in Go, and I have mainly a Node.js background, so I don't know exactly how to handle errors in Go-style, and also how to make the code more idiomatic.
I would like to know if it is possible to avoid all the if statements for error validations.


No.

This is the way errors are handled in Go. You get the error as return value and you handle it. You may return it, log it, print it or mute. You can panic with it, which is somewhat similar to exceptions. It's all up to you.

Check out this blog post to see reasoning behind the way errors are implemented.


  This is my second program in Go, and I have mainly a Node.js background, so I don't know exactly how to handle errors in Go-style, and also how to make the code more idiomatic.


Node.js also has an error convention which is carefully followed by community users. Same stands for Go.

To make code more idiomatic I suggest you to read more standard library code. It will help a lot. Simply every time you look through the docs click on function (or other identifier) to see the actual code behind it. It's is super easy and may reveal how the things work in Go.

Here follows annotated rewrite:

package main

import (
    "fmt"
    "os"
    "github.com/minio/minio-go"
    "github.com/kelseyhightower/envconfig"
)

// CamelCase is idiomatic in Go, but snake_case.
type AWS struct {
    Endpoint        string `envconfig:"ENDPOINT"`
    AccessKeyId     string `envconfig:"ACCESS_KEY_ID"`
    SecretAccessKey string `envconfig:"SECRET_ACCESS_KEY"`
    SSL             bool   `envconfig:"SSL"`
    Bucket          string `envconfig:"BUCKET"`
    BucketKey       string `envconfig:"BUCKET_KEY"`
    BucketExpiry    string `envconfig:"BUCKET_EXPIRY"`
}

// Exit will write error text to stderr and exit
// with non zero return code.
func Exit(err error) {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
}

func main() {
    var aws AWS

    // Fill configuration from enviroment variables
    err := envconfig.Process("aws", &amp;aws)
    if err != nil {
        Exit(err)
    }

    svc, err := minio.New(aws.Endpoint, aws.AccessKeyId, aws.SecretAccessKey, aws.SSL)
    if err != nil {
        Exit(err)
    }

    url, err := svc.PresignedPutObject(aws.Bucket, aws.BucketKey, aws.BucketExpiry)
    if err != nil {
        Exit(err)
    }

    // stdout is used only to print received URL
    fmt.Println(url)
}