Related
I have been unable to solve the problem into elasticsearch Bulk method for several days, since I am not strong in Go and started learning it not so long ago, while executing the code :
package main
import (
"bytes"
json "encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type BulkInsertMetaData struct {
Index []BulkInsertIndex `json:"index"`
}
type BulkInsertIndex struct {
Index string `json:"_index"`
ID string `json:"_id"`
}
type BulInsertData struct {
Url string `json:"url"`
}
func main() {
dataMeta := BulkInsertMetaData{
Index: []BulkInsertIndex{
{
Index: "Test",
ID: "1234567890",
},
},
}
data := BulInsertData{
Url: "http://XXXX.XX",
}
TojsBulInsertData, _ := json.Marshal(data)
TojsBulkInsertMetaData, _ := json.Marshal(dataMeta)
BulkMetaData := bytes.NewBuffer(append(TojsBulkInsertMetaData, []byte("\n")...))
BulkData := bytes.NewBuffer(append(TojsBulInsertData, []byte("\n")...))
log.Println(BulkMetaData)
log.Println(BulkData)
respMetaData, err := http.Post("http://127.0.0.1:9200/_bulk", "application/json", BulkMetaData)
if err != nil {
log.Println(err)
}
body, err := ioutil.ReadAll(respMetaData.Body)
if err != nil {
log.Println(err)
}
fmt.Println(string(body))
respBulkData, err := http.Post("http://127.0.0.1:9200/_bulk", "application/json", BulkData)
if err != nil {
log.Println(err)
}
body2, err := ioutil.ReadAll(respBulkData.Body)
if err != nil {
log.Println(err)
}
fmt.Println(string(body2))
}
but i get an error:
2022/02/09 14:37:02 {"index":[{"_index":"Test","_id":"1234567890"}]}
2022/02/09 14:37:02 {"url":"http://XXXX.XX"}
{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Malformed action/metadata line [1], expected START_OBJECT or END_OBJECT but found [START_ARRAY]"}],"type":"illegal_argument_exception","reason":"Malformed action/metadata line [1], expected START_OBJECT or END_OBJECT but found [START_ARRAY]"},"status":400}
please help and explain what I'm doing wrong, I searched the Internet for the answer to my question but did not find
I test insert when using REST client passes without problems
BulkMetaData should be {"index":{"_index":"Test","_id":"1234567890"}} (without []) and it should be sent to /_bulk together with BulkData, as a single payload:
{"index":{"_index":"Test","_id":"1234567890"}}
{"url":"http://XXXX.XX"}
Sorry for kinda necroing but I also recently needed to design a Bulk connector in our codebase and the fact that there are NO NDJSON encoder/decoders out on the web is appalling. Here is my implementation:
func ParseToNDJson(data []map[string]interface{}, dst *bytes.Buffer) error {
enc := json.NewEncoder(dst)
for _, element := range data {
if err := enc.Encode(element); err != nil {
if err != io.EOF {
return fmt.Errorf("failed to parse NDJSON: %v", err)
}
break
}
}
return nil
}
Driver code to test:
func main() {
var b bytes.Buffer
var data []map[string]interface{}
// pointless data generation...
for i, name := range []string{"greg", "sergey", "alex"} {
data = append(data, map[string]interface{}{name: i})
}
if err := ParseToNDJson(query, &body); err != nil {
return nil, fmt.Errorf("error encoding request: %s", err)
}
res, err := esapi.BulkRequest{
Index: "tasks",
Body: strings.NewReader(body.String()),
}.Do(ctx, q.es)
Hope this helps someone
I am trying to write a validation admission controller webhook which should reject the deployment if No Nodeselector is mentioned,
I am getting this error while creating the deployment -
Error from server (InternalError): error when creating "test.yaml": Internal error occurred: failed calling webhook "validatingwebhook.kube-system.svc": couldn't get version/kind; json parse error: invalid character '{' after top-level value
I have mention the sample code here, to check all the code please visit https://github.com/kumarshivam12/validation-kontroller
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
admissionv1 "k8s.io/api/admission/v1beta1"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
)
var (
scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme)
logger = log.New(os.Stdout, "http: ", log.LstdFlags)
)
func ValidatePod(w http.ResponseWriter, r *http.Request) {
// Validate that the incoming content type is correct.
if r.Header.Get("Content-Type") != "application/json" {
fmt.Println("expected application/json content-type")
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
responsewriters.InternalError(w, r, err)
fmt.Printf("Error %s, reading the body", err.Error())
}
grpversionkind := admissionv1.SchemeGroupVersion.WithKind("AdmissionReview")
var admissionReview admissionv1.AdmissionReview
_, _, err = codecs.UniversalDeserializer().Decode(body, &grpversionkind, &admissionReview)
if err != nil {
msg := fmt.Sprintf("error getting admission review from request: %v", err)
logger.Printf(msg)
w.WriteHeader(400)
w.Write([]byte(msg))
return
}
fmt.Printf("debug: %+v\n", admissionReview.Request.Resource)
var deployment appsv1.Deployment
_, _, err = codecs.UniversalDeserializer().Decode(body, nil, &deployment)
if err != nil {
msg := fmt.Sprintf("error getting deployment from request: %v", err)
logger.Printf(msg)
w.WriteHeader(400)
w.Write([]byte(msg))
return
}
resourceNodeselector := deployment.Spec.Template.Spec.NodeSelector
response := admissionv1.AdmissionResponse{}
if len(resourceNodeselector) == 0 {
response = admissionv1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: false,
Result: &v1.Status{
Message: fmt.Sprintf("The specified manifest Deployment %s Does not have the NodeSelector, NodeSelector is Mandatory Field", deployment.Name),
Status: "406",
},
}
} else {
response = admissionv1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
}
}
admissionReview.Response = &response
res, err := json.Marshal(admissionReview)
if err != nil {
fmt.Printf("error %s, while converting response to byte slice", err.Error())
}
_, err = w.Write(res)
if err != nil {
fmt.Printf("error %s, writing respnse to responsewriter", err.Error())
}
if err != nil {
fmt.Printf("error %s, while converting response to byte slice", err.Error())
}
_, err = w.Write(res)
if err != nil {
fmt.Printf("error %s, writing respnse to responsewriter", err.Error())
}
}
This is my code:
package main
import (
"context"
"log"
"fmt"
"github.com/chromedp/chromedp"
)
func main() {
queries := [3]string{"Object.keys(window);", "window.CSS", "window.Array"}
// create context
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
// run task list
var res []byte
err := chromedp.Run(ctx,
chromedp.Navigate(`https://www.google.com/`),
chromedp.ActionFunc(func(ctx context.Context) error {
for _, query := range queries {
err2 := chromedp.Evaluate(query, &res)
if err2 != nil {
fmt.Printf("error in ActionFunc: %s\n", err2)
}
fmt.Printf("Query %s outputs: %v\n", query, res)
}
return nil
}),
)
if err != nil {
log.Fatal(err)
}
}
What i am trying to do is to navigate to url to Evaluate and get values for a big list of queries (I reduced the array to 3 queries for the example).
and then it should just outputs the values from those queries.
But what i get is these errors for every iteration:
error in ActionFunc: %!s(chromedp.ActionFunc=0x7f25a0)
Query Object.keys(window); outputs: []
error in ActionFunc: %!s(chromedp.ActionFunc=0x7f25a0)
Query window.CSS outputs: []
error in ActionFunc: %!s(chromedp.ActionFunc=0x7f25a0)
Query window.Array outputs: []
chromedp.Evaluate does not return error. It returns EvaluateAction. It has Do func which accepts context. So you can try this;
queries := [3]string{"Object.keys(window);", "window.CSS", "window.Array"}
// create context
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
// run task list
var res []byte
err := chromedp.Run(ctx,
chromedp.Navigate(`https://www.google.com/`),
chromedp.WaitReady("body"),
//chromedp.Evaluate("Object.keys(window)", &res),
chromedp.ActionFunc(func(ctx context.Context) error {
for _, query := range queries {
chromedp.Evaluate(query, &res).Do(ctx)
fmt.Printf("Query %s outputs: %+v\n", query, string(res))
}
return nil
}),
)
if err != nil {
log.Fatal(err)
}
I'm building an application where I get muslim prayer data from multiple sources. The first being S3, the second being aladhan (a public api). I only want to get data from aladhan if it's not available in S3. If I do have to get the data from the public source then I upload it to my s3.
Here is the code:
This is my interface loop code. I've put in print statements to show that I'm running into the return statement twice, once with data in my return struct, the second time the struct is nil.
// prayeriface.go
package prayer
import (
"fmt"
)
type MonthPrayerIface interface {
GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error)
}
type PreCurrNextMonthPrayer struct {
custData *LookupInput
CurrentMonthData *PCal
PreviousMonthData *PCal
NextMonthData *PCal
prayers []MonthPrayerIface
}
func (p *PreCurrNextMonthPrayer) GetMonthPrayers() (*PreCurrNextMonthPrayer, error) {
var err error
var monthlyData *PreCurrNextMonthPrayer
defer func() {
fmt.Printf("return monthlyData address & value = %p %v\n", monthlyData, monthlyData)
}()
for k, data := range p.prayers {
fmt.Printf("loop = %v, data= %T %v\n", k, monthlyData, monthlyData)
monthlyData, err = data.GetMonthPrayer(p.custData)
fmt.Printf("\terr= %v\n", err)
fmt.Printf("\tmonthlyData= %p %v\n", monthlyData, monthlyData)
if err == nil {
fmt.Printf("loop-return: err == nil \n")
return monthlyData, nil
}
}
if err == nil {
fmt.Printf("post-loop:\n")
fmt.Printf("\tmonthlyData= %p %v\n", monthlyData, monthlyData)
return monthlyData, nil
}
return nil, fmt.Errorf("unable to get prayer data from all sources %s", err)
}
func NewMonthPrayer(input *LookupInput, prayers ...MonthPrayerIface) (*PreCurrNextMonthPrayer, error) {
var err error
t := &PreCurrNextMonthPrayer{
custData: input,
prayers: prayers,
}
t, err = t.GetMonthPrayers()
if err != nil {
return nil, err
}
return t, nil
}
As you can see, I'm looping over an interface struct method called GetMonthPrayer
This is my s3 source
// s3.go
package prayer
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"io"
awsservices "prayer-times/src/aws"
)
// S3Store s3 storage object for prayer calendars
type S3Store struct {
data *PCal
}
// GetMonthPrayer retrieves prayer data from s3, otherwise from aladhan
func (s *S3Store) GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
mPrayer := new(PreCurrNextMonthPrayer)
fmt.Println("attempting to retrieve prayer data from s3")
s3Client := awsservices.NewS3Service()
pMonthInput := &LookupInput{
Country: input.Country,
ZipCode: input.ZipCode,
custTime: input.custTime.AddDate(0, -1, 0),
}
nMonthInput := &LookupInput{
Country: input.Country,
ZipCode: input.ZipCode,
custTime: input.custTime.AddDate(0, 1, 0),
}
// s3Pdata retrieves data from S3 and
s3pData := func(input *LookupInput) (*PCal, error) {
pCalendar := new(PCal)
data, err := s3Client.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(
fmt.Sprintf(
"%s/%d/%d/%d",
input.Country,
input.ZipCode,
input.custTime.Year(),
input.custTime.Month())),
})
if err != nil {
return nil, err
}
if data == nil {
return nil, errors.New("error data from s3 is nil")
}
defer func() {
err := data.Body.Close()
if err != nil {
fmt.Printf("unable to close s3 body: %s", err)
}
}()
s3buf := bytes.NewBuffer(nil)
if _, err := io.Copy(s3buf, data.Body); err != nil {
return nil, err
}
dataBytes := s3buf.Bytes()
decoder := json.NewDecoder(bytes.NewReader(dataBytes))
err = decoder.Decode(&pCalendar)
if err != nil {
fmt.Printf("unable to decode json: %s", err)
}
return pCalendar, nil
}
aladhanData := new(AladhanStore)
getAladhanData := func(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
data, err := aladhanData.GetMonthPrayer(input)
if err != nil {
return nil, err
}
return data, nil
}
// Get current data from s3, if not s3, then get all three from aladhan
cMonthS3Data, err := s3pData(input)
pMonthS3Data, err := s3pData(pMonthInput)
nMonthS3Data, err := s3pData(nMonthInput)
if err != nil {
adata, err := getAladhanData(input)
if err != nil {
fmt.Printf("err: %s", err)
return nil, err
}
return adata, nil
}
mPrayer.CurrentMonthData = cMonthS3Data
// Get previous month data from s3, if not s3, then get all three from aladhan
mPrayer.PreviousMonthData = pMonthS3Data
// Get next month data from s3, if not s3, then get all three from aladhan
mPrayer.NextMonthData = nMonthS3Data
return mPrayer, nil
}
Here is my aladhan source
// aladhan.go
package prayer
import (
"bytes"
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"golang.org/x/sync/errgroup"
"io"
"log"
awsservices "prayer-times/src/aws"
"prayer-times/src/urljsonoutput"
"prayer-times/src/zipcoordinates"
)
var (
aladhanURL string = "https://api.aladhan.com/v1/calendar?"
)
// PCal contains the prayer times of the month as well as the return code
type PCal struct {
Code int `json:"code"`
Status string `json:"status"`
Data []struct {
Timings DailyPrayers
}
}
/*
AladhanData returns the total monthly prayers of given month, coordinates, and zip from aladhan.
https://api.aladhan.com/v1/calendar?latitude=51.508515&longitude=-0.1254872&method=1&month=4&year=2017
*/
func AladhanData(input *LookupInput) *PCal {
coordinates := zipcoordinates.HereCoordinates(&zipcoordinates.GeoLocationInput{
PostalCode: input.ZipCode,
CountryCode: input.Country,
})
respStruct := new(PCal)
_, err := urljsonoutput.GetURLJSON(fmt.Sprintf(
"%slatitude=%v&longitude=%v&method=%v&month=%v&year=%v",
aladhanURL,
coordinates.Items[0].Position.Latitude,
coordinates.Items[0].Position.Longitude,
input.Method,
int(input.custTime.Month()),
input.custTime.Year()), respStruct)
if err != nil {
log.Fatalf("unable to pull monthly prayer data %v", err)
}
return respStruct
}
// AladhanStore struct to interact with interface for GetMonthPrayer
type AladhanStore struct {
data *PCal
}
// GetMonthPrayer Pulls prayer data from aladhan
func (a *AladhanStore) GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
mPrayer := new(PreCurrNextMonthPrayer)
// Return prayer data from aladhan
custPMonthTime := input.custTime.AddDate(0, -1, 0)
pMonthLookupInput := new(LookupInput)
pMonthLookupInput.custTime = custPMonthTime
pMonthLookupInput.ZipCode = input.ZipCode
pMonthLookupInput.Country = input.Country
custNMonthTime := input.custTime.AddDate(0, 1, 0)
nMonthLookupInput := new(LookupInput)
nMonthLookupInput.custTime = custNMonthTime
nMonthLookupInput.ZipCode = input.ZipCode
nMonthLookupInput.Country = input.Country
prayerData := AladhanData(input)
pMonthPData := AladhanData(pMonthLookupInput)
nMonthPData := AladhanData(nMonthLookupInput)
// Save prayer data into io.Reader to save to s3
var Marshal = func(data interface{}) (io.ReadSeeker, error) {
mdata, err := json.MarshalIndent(data, "", "\t")
if err != nil {
return nil, err
}
return bytes.NewReader(mdata), nil
}
rmData, err := Marshal(prayerData)
pRmData, err := Marshal(pMonthPData)
nRmData, err := Marshal(nMonthPData)
if err != nil {
return nil, err
}
// Save prayer data into s3
g := new(errgroup.Group)
s3Upload := func(rawData *io.ReadSeeker, input *LookupInput) func() error {
return func() error {
s3Client := s3manager.NewUploaderWithClient(awsservices.NewS3Service())
_, err = s3Client.Upload(&s3manager.UploadInput{
Bucket: aws.String(bucket),
Key: aws.String(
fmt.Sprintf(
"%s/%d/%d/%d",
input.Country,
input.ZipCode,
input.custTime.Year(),
int(input.custTime.Month()))),
Body: *rawData,
})
if err != nil {
return err
}
return nil
}
}
g.Go(s3Upload(&pRmData, pMonthLookupInput))
g.Go(s3Upload(&rmData, input))
g.Go(s3Upload(&nRmData, nMonthLookupInput))
if err := g.Wait(); err == nil {
mPrayer.PreviousMonthData = pMonthPData
mPrayer.CurrentMonthData = prayerData
mPrayer.NextMonthData = nMonthPData
return mPrayer, nil
}
return nil, err
}
Here is my test file.
func TestPrayer(t *testing.T) {
p, err := NewMonthPrayer(
&input,
&S3Store{},
&AladhanStore{},
)
if err != nil {
t.Errorf("error: %s", err)
}
data, err := p.GetMonthPrayers()
if err != nil {
t.Errorf("error: %s", err)
}
t.Logf("Test address: %p", data)
t.Logf("data THIS SHOULDN'T BE NIL: %v", data)
t.Logf("ERROR: %s", err)
}
These are my results. Ignore the pass result, the data is first not nil and second nil.
=== RUN TestPrayer
loop = 0, data= *prayer.PreCurrNextMonthPrayer <nil>
attempting to retrieve prayer data from s3
err= <nil>
monthlyData= 0xc000131180 &{<nil> 0xc0002612f0 0xc00051e780 0xc00011cea0 []}
loop-return: err == nil
return monthlyData address & value = 0xc000131180 &{<nil> 0xc0002612f0 0xc00051e780 0xc00011cea0 []}
post-loop:
monthlyData= 0x0 <nil>
return monthlyData address & value = 0x0 <nil>
prayer_test.go:53: Test address: 0x0
prayer_test.go:55: data THIS SHOULDN'T BE NIL: <nil>
prayer_test.go:56: ERROR: %!s(<nil>)
--- PASS: TestPrayer (0.32s)
PASS
The duplicate was due to the GetMonthPrayer call from NewMonthPrayer, which shouldn't have been the case to begin with. It was called first but returned second, thus overwriting the existing data.
func NewMonthPrayer(input *LookupInput, prayers ...MonthPrayerIface) (*PreCurrNextMonthPrayer, error) {
var err error
t := &PreCurrNextMonthPrayer{
custData: input,
prayers: prayers,
}
t, err = t.GetMonthPrayers()
if err != nil {
return nil, err
}
return t, nil
}
I removed the NewMonthPrayer entirely as it was unnecessary, I also removed the function call in the process, thus fixing the initial problem.
// NewPrayer instantiates a prayer type object with the required input
func NewPrayer(input *LookupInput, prayers ...MonthPrayerIface) *Prayer {
return &Prayer{
custData: input,
prayers: prayers,
}
}
This is what I have to create nested buckets. It does not return any error but fails at creating nested bucket under another nested bucket.
func CreateNestedBuckets(buckets []string) error {
err := db.Update(func(tx *bolt.Tx) error {
var bkt *bolt.Bucket
var err error
first := true
for _, bucket := range buckets {
log.Error(bucket)
if first == true {
bkt, err = tx.CreateBucketIfNotExists([]byte(bucket))
first = false
} else {
bkt, err = bkt.CreateBucketIfNotExists([]byte(bucket))
}
if err != nil {
log.Error("error creating nested bucket")
return err
}
}
return nil
})
if err != nil {
log.Error("error creating nested bucket!!!")
return err
}
return nil
}
Short answer: yes! You can have nested buckets: https://twitter.com/boltdb/status/454730212010254336
Long answer: your code works fine! Heres some things to check though:
Are you checking the correct bolt database file? The botlt db file will be created in the directory you run your code from, unless you've specified an absolute path.
Does your input actually contain enough elements to create a nested structure?
I've ran your code with the following setup (a couple of small changes but nothing major) and it works fine:
package main
import (
"log"
"os"
"time"
"github.com/boltdb/bolt"
)
var dbname = "test.bdb"
var dbperms os.FileMode = 0770
var options = &bolt.Options{Timeout: 1 * time.Second}
func main() {
var names []string
names = append(names, "bucketOne")
names = append(names, "bucketTwo")
names = append(names, "bucketThree")
if err := CreateNestedBuckets(names); err != nil {
log.Fatal(err)
}
}
// CreateNestedBuckets - Function to create
// nested buckets from an array of Strings
func CreateNestedBuckets(buckets []string) error {
db, dberr := bolt.Open(dbname, dbperms, options)
if dberr != nil {
log.Fatal(dberr)
}
defer db.Close()
err := db.Update(func(tx *bolt.Tx) error {
var bkt *bolt.Bucket
var err error
first := true
for _, bucket := range buckets {
log.Println(bucket)
if first == true {
bkt, err = tx.CreateBucketIfNotExists([]byte(bucket))
first = false
} else {
bkt, err = bkt.CreateBucketIfNotExists([]byte(bucket))
}
if err != nil {
log.Println("error creating nested bucket")
return err
}
}
return nil
})
if err != nil {
log.Println("error creating nested bucket!!!")
return err
}
return nil
}
To test you can cat the file through the strings command:
cat test.bdb | strings
bucketThree
bucketTwo
bucketOne
If you're on Windows, I'm not sure what the equivalent command is, but you can open the file with Notepad and inspect it manually. It won't be pretty, but you should still see the name of your buckets in there.
On another note, you error handling is going to result in very similar messages being printed in succession. Here's a slightly cleaner solution you can use:
// CreateNestedBucketsNew - function to create
// nested buckets from an array of Strings - my implementation
func CreateNestedBucketsNew(buckets []string) (err error) {
err = db.Update(func(tx *bolt.Tx) (err error) {
var bkt *bolt.Bucket
for index, bucket := range buckets {
if index == 0 {
bkt, err = tx.CreateBucketIfNotExists([]byte(bucket))
} else {
bkt, err = bkt.CreateBucketIfNotExists([]byte(bucket))
}
if err != nil {
return fmt.Errorf("Error creating nested bucket [%s]: %v", bucket, err)
}
}
return err
})
return err
}
fste89's demo has some debug;
this right:
package main
import (
"fmt"
"time"
"github.com/boltdb/bolt"
)
func CreateNestedBuckets(fatherTable string, sonTabls []string) error {
db, dberr := bolt.Open("your file path", 0600, &bolt.Options{Timeout: 1 * time.Second})
if dberr != nil {
fmt.Println(dberr)
}
defer db.Close()
err := db.Update(func(tx *bolt.Tx) error {
var bkt *bolt.Bucket
var err error
bkFather, err = tx.CreateBucketIfNotExists([]byte(fatherTable))
for _, ta := range sonTabls {
fmt.Println(ta)
_, err = bkFather.CreateBucketIfNotExists([]byte(ta))
if err != nil {
fmt.Println("error creating nested bucket")
return err
}
}
return nil
})
if err != nil {
fmt.Println("error creating nested bucket!!!")
return err
}
return nil
}
func main() {
t := []string{"cc", "1", "2", "3"}
fmt.Println(CreateNestedBuckets("sb", t))
}
echo:
cc
1
2
3
<nil>
Visible
enter image description here
func CreateNestedBuckets(fatherTable string, sonTables []string) error {
db, dberr := bolt.Open("E:\\OneDrive\\code\\go\\project\\transmission\\static\\localstorage.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
if dberr != nil {
fmt.Println(dberr)
}
defer db.Close()
err := db.Update(func(tx *bolt.Tx) error {
var err error
bkFather, err := tx.CreateBucketIfNotExists([]byte(fatherTable))
for _, ta := range sonTables {
fmt.Println(ta)
_, err = bkFather.CreateBucketIfNotExists([]byte(ta))
if err != nil {
fmt.Println("error creating nested bucket")
return err
}
}
return nil
})
if err != nil {
fmt.Println("error creating nested bucket!!!")
return err
}
return nil
}