diff --git a/.gitignore b/.gitignore index f72f0cd..ba1a829 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ _testmain.go .idea/ # Output of the go coverage tool, specifically when used with LiteIDE -*.out \ No newline at end of file +*.out +*.orig diff --git a/README.md b/README.md index 5d1102e..5ac1df8 100644 --- a/README.md +++ b/README.md @@ -15,96 +15,96 @@ A curated collection of idiomatic design & application patterns for Go language. | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Abstract Factory](/creational/abstract_factory.md) | Provides an interface for creating families of releated objects | ✘ | -| [Builder](/creational/builder.md) | Builds a complex object using simple objects | ✔ | -| [Factory Method](/creational/factory.md) | Defers instantiation of an object to a specialized function for creating instances | ✔ | -| [Object Pool](/creational/object-pool.md) | Instantiates and maintains a group of objects instances of the same type | ✔ | -| [Singleton](/creational/singleton.md) | Restricts instantiation of a type to one object | ✔ | +| [Abstract Factory](/creational/abstract_factory.md) | Provides an interface for creating families of releated objects | | +| [Builder](/creational/builder.md) | Builds a complex object using simple objects | | +| [Factory Method](/creational/factory.md) | Defers instantiation of an object to a specialized function for creating instances | | +| [Object Pool](/creational/object-pool.md) | Instantiates and maintains a group of objects instances of the same type | | +| [Singleton](/creational/singleton.md) | Restricts instantiation of a type to one object | | ## Structural Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Bridge](/structural/bridge/main.go) | Decouples an interface from its implementation so that the two can vary independently | ✔ | -| [Composite](/structural/composite/main.go) | Encapsulates and provides access to a number of different objects | ✔ | -| [Decorator](/structural/decorator.md) | Adds behavior to an object, statically or dynamically | ✔ | -| [Facade](/structural/facade/main.go) | Uses one type as an API to a number of others | ✔ | -| [Flyweight](/structural/flyweight/main.go) | Reuses existing instances of objects with similar/identical state to minimize resource usage | ✔ | -| [Proxy](/structural/proxy.md) | Provides a surrogate for an object to control it's actions | ✔ | +| [Bridge](/structural/bridge/main.go) | Decouples an interface from its implementation so that the two can vary independently | | +| [Composite](/structural/composite/main.go) | Encapsulates and provides access to a number of different objects | | +| [Decorator](/structural/decorator.md) | Adds behavior to an object, statically or dynamically | | +| [Facade](/structural/facade/main.go) | Uses one type as an API to a number of others | | +| [Flyweight](/structural/flyweight/main.go) | Reuses existing instances of objects with similar/identical state to minimize resource usage | | +| [Proxy](/structural/proxy.md) | Provides a surrogate for an object to control it's actions | | ## Behavioral Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Chain of Responsibility](/behavioral/chain_of_responsibility/main.go) | Avoids coupling a sender to receiver by giving more than object a chance to handle the request | ✔ | -| [Command](/behavioral/command/main.go) | Bundles a command and arguments to call later | ✔ | -| [Mediator](/behavioral/mediator/main.go) | Connects objects and acts as a proxy | ✔ | -| [Memento](/behavioral/memento/main.go) | Generate an opaque token that can be used to go back to a previous state | ✔ | -| [Observer](/behavioral/observer.md) | Provide a callback for notification of events/changes to data | ✔ | -| [Registry](/behavioral/registry.md) | Keep track of all subclasses of a given class | ✘ | -| [State](/behavioral/state/main.go) | Encapsulates varying behavior for the same object based on its internal state | ✔ | -| [Strategy](/behavioral/strategy.md) | Enables an algorithm's behavior to be selected at runtime | ✔ | -| [Template](/behavioral/template/main.go) | Defines a skeleton class which defers some methods to subclasses | ✔ | -| [Visitor](/behavioral/visitor/main.go) | Separates an algorithm from an object on which it operates | ✔ | +| [Chain of Responsibility](/behavioral/chain_of_responsibility/main.go) | Avoids coupling a sender to receiver by giving more than object a chance to handle the request | | +| [Command](/behavioral/command/main.go) | Bundles a command and arguments to call later | | +| [Mediator](/behavioral/mediator/main.go) | Connects objects and acts as a proxy | | +| [Memento](/behavioral/memento/main.go) | Generate an opaque token that can be used to go back to a previous state | | +| [Observer](/behavioral/observer.md) | Provide a callback for notification of events/changes to data | | +| [Registry](/behavioral/registry.md) | Keep track of all subclasses of a given class | | +| [State](/behavioral/state/main.go) | Encapsulates varying behavior for the same object based on its internal state | | +| [Strategy](/behavioral/strategy.md) | Enables an algorithm's behavior to be selected at runtime | | +| [Template](/behavioral/template/main.go) | Defines a skeleton class which defers some methods to subclasses | | +| [Visitor](/behavioral/visitor/main.go) | Separates an algorithm from an object on which it operates | | ## Synchronization Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Condition Variable](/synchronization/condition_variable.md) | Provides a mechanism for threads to temporarily give up access in order to wait for some condition | ✘ | -| [Lock/Mutex](/synchronization/mutex.md) | Enforces mutual exclusion limit on a resource to gain exclusive access | ✘ | -| [Monitor](/synchronization/monitor.md) | Combination of mutex and condition variable patterns | ✘ | -| [Read-Write Lock](/synchronization/read_write_lock.md) | Allows parallel read access, but only exclusive access on write operations to a resource | ✘ | -| [Semaphore](/synchronization/semaphore.md) | Allows controlling access to a common resource | ✔ | +| [Condition Variable](/synchronization/condition_variable.md) | Provides a mechanism for threads to temporarily give up access in order to wait for some condition | | +| [Lock/Mutex](/synchronization/mutex.md) | Enforces mutual exclusion limit on a resource to gain exclusive access | | +| [Monitor](/synchronization/monitor.md) | Combination of mutex and condition variable patterns | | +| [Read-Write Lock](/synchronization/read_write_lock.md) | Allows parallel read access, but only exclusive access on write operations to a resource | | +| [Semaphore](/synchronization/semaphore.md) | Allows controlling access to a common resource | | ## Concurrency Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [N-Barrier](/concurrency/n_barrier/main.go) | Prevents a process from proceeding until all N processes reach to the barrier | ✔ | -| [Bounded Parallelism](/concurrency/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | ✔ | -| [Broadcast](/concurrency/broadcast.md) | Transfers a message to all recipients simultaneously | ✘ | -| [Coroutines](/concurrency/coroutine.md) | Subroutines that allow suspending and resuming execution at certain locations | ✘ | -| [Generators](/concurrency/generator.md) | Yields a sequence of values one at a time | ✔ | -| [Reactor](/concurrency/reactor.md) | Demultiplexes service requests delivered concurrently to a service handler and dispatches them syncronously to the associated request handlers | ✘ | -| [Parallelism](/concurrency/parallelism.md) | Completes large number of independent tasks | ✔ | -| [Producer Consumer](/concurrency/producer_consumer.md) | Separates tasks from task executions | ✘ | +| [N-Barrier](/concurrency/n_barrier/main.go) | Prevents a process from proceeding until all N processes reach to the barrier | | +| [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | | +| [Broadcast](/concurrency/broadcast.md) | Transfers a message to all recipients simultaneously | | +| [Coroutines](/concurrency/coroutine.md) | Subroutines that allow suspending and resuming execution at certain locations | | +| [Generators](/concurrency/generator.md) | Yields a sequence of values one at a time | | +| [Reactor](/concurrency/reactor.md) | Demultiplexes service requests delivered concurrently to a service handler and dispatches them syncronously to the associated request handlers | | +| [Parallelism](/concurrency/parallelism.md) | Completes large number of independent tasks | | +| [Producer Consumer](/concurrency/producer_consumer.md) | Separates tasks from task executions | | ## Messaging Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Fan-In](/messaging/fan_in.md) | Funnels tasks to a work sink (e.g. server) | ✔ | -| [Fan-Out](/messaging/fan_out.md) | Distributes tasks among workers (e.g. producer) | ✔ | -| [Futures & Promises](/messaging/futures_promises.md) | Acts as a place-holder of a result that is initially unknown for synchronization purposes | ✘ | -| [Publish/Subscribe](/messaging/publish_subscribe.md) | Passes information to a collection of recipients who subscribed to a topic | ✔ | -| [Push & Pull](/messaging/push_pull.md) | Distributes messages to multiple workers, arranged in a pipeline | ✘ | +| [Fan-In](/messaging/fan_in.md) | Funnels tasks to a work sink (e.g. server) | | +| [Fan-Out](/messaging/fan_out.md) | Distributes tasks among workers (e.g. producer) | | +| [Futures & Promises](/messaging/futures_promises.md) | Acts as a place-holder of a result that is initially unknown for synchronization purposes | | +| [Publish/Subscribe](/messaging/publish_subscribe.md) | Passes information to a collection of recipients who subscribed to a topic | | +| [Push & Pull](/messaging/push_pull.md) | Distributes messages to multiple workers, arranged in a pipeline | | ## Stability Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Bulkheads](/stability/bulkhead.md) | Enforces a principle of failure containment (i.e. prevents cascading failures) | ✘ | -| [Circuit-Breaker](/stability/circuit-breaker.md) | Stops the flow of the requests when requests are likely to fail | ✔ | -| [Deadline](/stability/deadline.md) | Allows clients to stop waiting for a response once the probability of response becomes low (e.g. after waiting 10 seconds for a page refresh) | ✘ | -| [Fail-Fast](/stability/fail_fast.md) | Checks the availability of required resources at the start of a request and fails if the requirements are not satisfied | ✘ | -| [Handshaking](/stability/handshaking.md) | Asks a component if it can take any more load, if it can't, the request is declined | ✘ | -| [Steady-State](/stability/steady_state.md) | For every service that accumulates a resource, some other service must recycle that resource | ✘ | +| [Bulkheads](/stability/bulkhead.md) | Enforces a principle of failure containment (i.e. prevents cascading failures) | | +| [Circuit-Breaker](/stability/circuit-breaker.md) | Stops the flow of the requests when requests are likely to fail | | +| [Deadline](/stability/deadline.md) | Allows clients to stop waiting for a response once the probability of response becomes low (e.g. after waiting 10 seconds for a page refresh) | | +| [Fail-Fast](/stability/fail_fast.md) | Checks the availability of required resources at the start of a request and fails if the requirements are not satisfied | | +| [Handshaking](/stability/handshaking.md) | Asks a component if it can take any more load, if it can't, the request is declined | | +| [Steady-State](/stability/steady_state.md) | For every service that accumulates a resource, some other service must recycle that resource | | ## Profiling Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Timing Functions](/profiling/timing.md) | Wraps a function and logs the execution | ✔ | +| [Timing Functions](/profiling/timing.md) | Wraps a function and logs the execution | | ## Idioms | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Functional Options](/idiom/functional-options.md) | Allows creating clean APIs with sane defaults and idiomatic overrides | ✔ | +| [Functional Options](/idiom/functional-options.md) | Allows creating clean APIs with sane defaults and idiomatic overrides | | ## Anti-Patterns | Pattern | Description | Status | |:-------:|:----------- |:------:| -| [Cascading Failures](/anti-patterns/cascading_failures.md) | A failure in a system of interconnected parts in which the failure of a part causes a domino effect | ✘ | +| [Cascading Failures](/anti-patterns/cascading_failures.md) | A failure in a system of interconnected parts in which the failure of a part causes a domino effect | | diff --git a/SUMMARY.md b/SUMMARY.md index 9337c64..61e09c1 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -33,7 +33,7 @@ * [Semaphore](/synchronization/semaphore.md) * [Concurrency Patterns](/README.md#concurrency-patterns) * [N-Barrier](/concurrency/barrier.md) - * [Bounded Parallelism](/concurrency/bounded_parallelism.md) + * [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md) * [Broadcast](/concurrency/broadcast.md) * [Coroutines](/concurrency/coroutine.md) * [Generators](/concurrency/generator.md) diff --git a/behavioral/observer/main.go b/behavioral/observer/main.go index d6fbc9f..a6a3a65 100644 --- a/behavioral/observer/main.go +++ b/behavioral/observer/main.go @@ -40,11 +40,11 @@ type ( ) type ( - eventObserver struct{ + eventObserver struct { id int } - eventNotifier struct{ + eventNotifier struct { // Using a map with an empty struct allows us to keep the observers // unique while still keeping memory usage relatively low. observers map[Observer]struct{} @@ -84,10 +84,10 @@ func main() { tick := time.NewTicker(time.Second).C for { select { - case <- stop: + case <-stop: return case t := <-tick: n.Notify(Event{Data: t.UnixNano()}) } } -} \ No newline at end of file +} diff --git a/concurrency/bounded_parallelism.go b/concurrency/bounded/bounded_parallelism.go similarity index 100% rename from concurrency/bounded_parallelism.go rename to concurrency/bounded/bounded_parallelism.go diff --git a/concurrency/bounded_parallelism.md b/concurrency/bounded/bounded_parallelism.md similarity index 71% rename from concurrency/bounded_parallelism.md rename to concurrency/bounded/bounded_parallelism.md index 8f1429c..759485b 100644 --- a/concurrency/bounded_parallelism.md +++ b/concurrency/bounded/bounded_parallelism.md @@ -1,6 +1,6 @@ # Bounded Parallelism Pattern -[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](parallelism.md), but allows limits to be placed on allocation. +[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](../parallelism.md), but allows limits to be placed on allocation. # Implementation and Example diff --git a/playground/basic/address_test.go b/playground/basic/address_test.go new file mode 100644 index 0000000..dec36ec --- /dev/null +++ b/playground/basic/address_test.go @@ -0,0 +1,40 @@ +package basic + +import ( + "fmt" + "testing" +) + +func TestPrintAddress(t *testing.T) { + var a int + fmt.Printf("%T, %v, %p \n", a, a, &a) + passByVariable(a) + passByPointer(&a) +} + +func passByVariable(a int) { + fmt.Printf("%T, %v, %p \n", a, a, &a) +} + +func passByPointer(a *int) { + fmt.Printf("%T, %v, %p \n", a, a, &a) + fmt.Printf("%T, %v, %p \n", *a, *a, &*a) +} + +type robot struct{} + +func TestStructAddress(t *testing.T) { + var a robot + fmt.Printf("%T, %v, %p \n", a, a, &a) + passStructByVariable(a) + passStructByPointer(&a) +} + +func passStructByVariable(a robot) { + fmt.Printf("[passStructByVariable] %T, %v, %p \n", a, a, &a) +} + +func passStructByPointer(a *robot) { + fmt.Printf("[passStructByPointer] %T, %v, %p \n", a, a, &a) + fmt.Printf("[passStructByPointer] %T, %v, %p \n", *a, *a, &*a) +} diff --git a/playground/cbor/2.png b/playground/cbor/2.png new file mode 100644 index 0000000..9131400 Binary files /dev/null and b/playground/cbor/2.png differ diff --git a/playground/cbor/cbor2_test.go b/playground/cbor/cbor2_test.go new file mode 100644 index 0000000..77f1975 --- /dev/null +++ b/playground/cbor/cbor2_test.go @@ -0,0 +1,53 @@ +package cbor + +import ( + "bytes" + "fmt" + "testing" + + "github.com/2tvenom/cbor" +) + +type Image struct { + Name string + Content []byte +} + +func TestCborEncode2(t *testing.T) { + // Read origin file + b := new(bytes.Buffer) + err := getImageBytes("./on.png", b) + if err != nil { + fmt.Println(err) + return + } + origin := b.Bytes() + + //image := &Image{Name:"on",Content:origin} + + // Encode + fmt.Println("--------- Encode ---------") + + var buf bytes.Buffer + encoder := cbor.NewEncoder(&buf) + ok, error := encoder.Marshal(origin) + + //check binary string + if !ok { + fmt.Errorf("Error decoding %s", error) + } else { + fmt.Println("Size: ", len(buf.Bytes())) + } + + // Decode + //fmt.Println("--------- Decode ---------",buf.Bytes()) + //var img []byte + //ok, err = encoder.Unmarshal(buf.Bytes(), &img) + //if !ok { + // fmt.Printf("Error Unmarshal %s", err) + // return + //} + ////output + //fmt.Printf("%v", img) + +} diff --git a/playground/cbor/cbor3_test.go b/playground/cbor/cbor3_test.go new file mode 100644 index 0000000..b71ac18 --- /dev/null +++ b/playground/cbor/cbor3_test.go @@ -0,0 +1,48 @@ +package cbor + +import ( + "bytes" + "fmt" + "testing" + + "go.mozilla.org/cose" +) + +func TestCborEncode3(t *testing.T) { + // Read origin file + b := new(bytes.Buffer) + err := getImageBytes("./on.png", b) + if err != nil { + fmt.Println(err) + return + } + origin := b.Bytes() + + //image := &Image{Name:"on",Content:origin} + fmt.Println("Size: ", len(origin)) + // Encode + fmt.Println("--------- Encode ---------") + + encoded, error := cose.Marshal(origin) + + if error != nil { + fmt.Errorf("Error decoding %s", error) + } else { + fmt.Println("Size: ", len(encoded)) + //fmt.Println("Content: ",string(encoded)) + } + + // Decode + fmt.Println("--------- Decode ---------") + //var img Image + unmarshal, err := cose.Unmarshal(encoded) + if err != nil { + fmt.Printf("Error Unmarshal %s", err) + return + } else { + fmt.Println("Size: ", len(unmarshal.([]byte))) + //fmt.Println("Content: ",unmarshal.([]byte)) + } + writeToFile("3", unmarshal.([]byte)) + +} diff --git a/playground/cbor/cbor_test.go b/playground/cbor/cbor_test.go new file mode 100644 index 0000000..cba4f8a --- /dev/null +++ b/playground/cbor/cbor_test.go @@ -0,0 +1,104 @@ +package cbor + +import ( + "bufio" + "bytes" + "fmt" + "image" + "image/jpeg" + "image/png" + "log" + "os" + "testing" + + "github.com/ugorji/go/codec" +) + +func TestCborEncode(t *testing.T) { + // Read origin file + buf := new(bytes.Buffer) + err := getImageBytes("./on.png", buf) + if err != nil { + fmt.Println(err) + return + } + origin := buf.Bytes() + + fmt.Println("size:", len(origin)) + writeToFile("1", origin) + + // Encode + encoded, err := encodeBinaryValue(buf.Bytes()) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println("size:", len(encoded)) + writeToFile("2", encoded) + + // Decode + decoded, err := decodeBinaryValue(encoded) + fmt.Println("size:", len(decoded)) + writeToFile("3", decoded) +} + +func encodeBinaryValue(b []byte) ([]byte, error) { + var ch codec.CborHandle + buf := new(bytes.Buffer) + + enc := codec.NewEncoder(buf, &ch) + err := enc.Encode(&b) + + return buf.Bytes(), err +} + +func decodeBinaryValue(b []byte) ([]byte, error) { + var ch codec.CborHandle + var decoded []byte + var bufReader = bufio.NewReader(bytes.NewReader(b)) + var dec = codec.NewDecoder(bufReader, &ch) + var err = dec.Decode(&decoded) + return decoded, err +} + +func getImageBytes(imgFile string, buf *bytes.Buffer) error { + // Read existing image from file + img, err := os.Open(imgFile) + if err != nil { + return err + } + defer img.Close() + + // TODO: Attach MediaType property, determine if decoding + // early is required (to optimize edge processing) + + // Expect "png" or "jpeg" image type + imageData, imageType, err := image.Decode(img) + if err != nil { + return err + } + // Finished with file. Reset file pointer + img.Seek(0, 0) + if imageType == "jpeg" { + err = jpeg.Encode(buf, imageData, nil) + if err != nil { + return err + } + } else if imageType == "png" { + err = png.Encode(buf, imageData) + if err != nil { + return err + } + } + return nil +} + +func writeToFile(fileName string, b []byte) { + f, _ := os.Create(fileName) + n2, err := f.Write(b) + if err != nil { + log.Fatal(err) + } + fmt.Printf("wrote file %d bytes\n", n2) +} diff --git a/playground/cbor/on.png b/playground/cbor/on.png new file mode 100644 index 0000000..8849ff6 Binary files /dev/null and b/playground/cbor/on.png differ diff --git a/playground/codecoverage/size.go b/playground/codecoverage/size.go new file mode 100644 index 0000000..ec52f77 --- /dev/null +++ b/playground/codecoverage/size.go @@ -0,0 +1,17 @@ +package codecoverage + +func Size(a int) string { + switch { + case a < 0: + return "negative" + case a == 0: + return "zero" + case a < 10: + return "small" + case a < 100: + return "big" + case a < 1000: + return "huge" + } + return "enormous" +} diff --git a/playground/codecoverage/size_test.go b/playground/codecoverage/size_test.go new file mode 100644 index 0000000..8fbdca2 --- /dev/null +++ b/playground/codecoverage/size_test.go @@ -0,0 +1,26 @@ +package codecoverage + +import "testing" + +type Test struct { + in int + out string +} + +var tests = []Test{ + {-1, "negative"}, + {0, "zero"}, + {5, "small"}, + {99, "big"}, + {100, "huge"}, + {10001, "enormous"}, +} + +func TestSize(t *testing.T) { + for i, test := range tests { + size := Size(test.in) + if size != test.out { + t.Errorf("#%d: Size(%d)=%s; want %s", i, test.in, size, test.out) + } + } +} diff --git a/playground/cron/cron_test.go b/playground/cron/cron_test.go new file mode 100644 index 0000000..6daa726 --- /dev/null +++ b/playground/cron/cron_test.go @@ -0,0 +1,86 @@ +package cron + +import ( + "fmt" + "testing" + "time" + + "github.com/edgexfoundry/edgex-go/pkg/models" + "github.com/robfig/cron" +) + +type Job struct { + schedule models.Schedule + scheduleEvents []models.ScheduleEvent +} + +func (job Job) Run() { + fmt.Println(job.schedule.Name, job.schedule.Frequency) +} + +func TestCronWithAddJob(t *testing.T) { + var job = Job{ + schedule: models.Schedule{ + Id: "xxx", + Name: "5sec-schedule", + Frequency: "PT5S", + }, + scheduleEvents: []models.ScheduleEvent{}, + } + var job2 = Job{ + schedule: models.Schedule{ + Id: "xxx", + Name: "2sec-schedule", + Frequency: "PT2S", + }, + scheduleEvents: []models.ScheduleEvent{}, + } + + // init cron + c := cron.New() + + // add cron job + var spec = fmt.Sprintf("@every %v", ParseDuration(job.schedule.Frequency)) + c.AddJob(spec, job) + + spec = fmt.Sprintf("@every %v", ParseDuration(job2.schedule.Frequency)) + c.AddJob(spec, job2) + + // start cron + c.Start() + + time.Sleep(10 * time.Second) + // keep alive + //select {} +} + +func TestCronWithAddFunc(t *testing.T) { + // init cron + c := cron.New() + + // add cron job + var duration = ParseDuration("PT2S") + var spec = fmt.Sprintf("@every %v", duration) + + c.AddFunc(spec, func() { + // @every 2s + fmt.Println(spec) + }) + + // start cron + c.Start() + + // keep alive + select {} +} + +func TestParseISO8601(t *testing.T) { + var duration = ParseDuration("PT2S") + + // PT2S -> 2s + fmt.Println(duration) + // PT15M -> 15m0s + fmt.Println(ParseDuration("PT15M")) + // P12Y4MT15M -> 108000h15m0s + fmt.Println(ParseDuration("P12Y4MT15M")) +} diff --git a/playground/cron/iso8601parser.go b/playground/cron/iso8601parser.go new file mode 100644 index 0000000..509d87c --- /dev/null +++ b/playground/cron/iso8601parser.go @@ -0,0 +1,35 @@ +package cron + +import ( + "regexp" + "strconv" + "time" +) + +func ParseDuration(str string) time.Duration { + durationRegex := regexp.MustCompile(`P(?P\d+Y)?(?P\d+M)?(?P\d+D)?T?(?P\d+H)?(?P\d+M)?(?P\d+S)?`) + matches := durationRegex.FindStringSubmatch(str) + + years := ParseInt64(matches[1]) + months := ParseInt64(matches[2]) + days := ParseInt64(matches[3]) + hours := ParseInt64(matches[4]) + minutes := ParseInt64(matches[5]) + seconds := ParseInt64(matches[6]) + + hour := int64(time.Hour) + minute := int64(time.Minute) + second := int64(time.Second) + return time.Duration(years*24*365*hour + months*30*24*hour + days*24*hour + hours*hour + minutes*minute + seconds*second) +} + +func ParseInt64(value string) int64 { + if len(value) == 0 { + return 0 + } + parsed, err := strconv.Atoi(value[:len(value)-1]) + if err != nil { + return 0 + } + return int64(parsed) +} diff --git a/playground/factory/robot.go b/playground/factory/robot.go new file mode 100644 index 0000000..9f6944f --- /dev/null +++ b/playground/factory/robot.go @@ -0,0 +1,14 @@ +package factory + +import "log" + +var speakFuncs = make(map[string]interface{}) + +func say(funcName string) { + speakFunc, ok := speakFuncs[funcName] + if !ok { + log.Println("speakFunc not exist") + } else { + speakFunc.(func())() + } +} diff --git a/playground/factory/robot_test.go b/playground/factory/robot_test.go new file mode 100644 index 0000000..c8355ba --- /dev/null +++ b/playground/factory/robot_test.go @@ -0,0 +1,8 @@ +package factory + +import "testing" + +func TestSay(t *testing.T) { + say("xxx") + say("hi") +} diff --git a/playground/factory/robotfuncs.go b/playground/factory/robotfuncs.go new file mode 100644 index 0000000..cb68aed --- /dev/null +++ b/playground/factory/robotfuncs.go @@ -0,0 +1,16 @@ +package factory + +import "log" + +func sayHi() { + log.Print("Hi~") +} + +func sayHello() { + log.Print("Hello~") +} + +func init() { + speakFuncs["hi"] = sayHi + speakFuncs["hello"] = sayHello +} diff --git a/playground/goroutine/basic_chan_test.go b/playground/goroutine/basic_chan_test.go new file mode 100644 index 0000000..7403897 --- /dev/null +++ b/playground/goroutine/basic_chan_test.go @@ -0,0 +1,24 @@ +package goroutine + +import ( + "fmt" + "testing" + "time" +) + +func TestFiveGopherWithChan(t *testing.T) { + c := make(chan int) + for i := 0; i < 5; i++ { + go sleepyGopherWithChan(i, c) + } + for i := 0; i < 5; i++ { + gopherID := <-c + fmt.Println("gopher ", gopherID, " has finished sleeping") + } +} + +func sleepyGopherWithChan(id int, c chan int) { + time.Sleep(2 * time.Second) + fmt.Println("... ", id, " snore ...") + c <- id +} diff --git a/playground/goroutine/basic_test.go b/playground/goroutine/basic_test.go new file mode 100644 index 0000000..02b2347 --- /dev/null +++ b/playground/goroutine/basic_test.go @@ -0,0 +1,25 @@ +package goroutine + +import ( + "fmt" + "testing" + "time" +) + +func TestOneGopher(t *testing.T) { + go sleepyGopher(1) + time.Sleep(3 * time.Second) +} + +func TestFiveGopher(t *testing.T) { + c := make(chan int) + for i := 0; i < 5; i++ { + go sleepyGopherWithChan(i, c) + } + time.Sleep(3 * time.Second) +} + +func sleepyGopher(id int) { + time.Sleep(2 * time.Second) + fmt.Println("... ", id, " snore ...") +} diff --git a/playground/goroutine/basic_waitgroup_test.go b/playground/goroutine/basic_waitgroup_test.go new file mode 100644 index 0000000..9eab546 --- /dev/null +++ b/playground/goroutine/basic_waitgroup_test.go @@ -0,0 +1,32 @@ +package goroutine + +import ( + "fmt" + "sync" + "testing" + "time" +) + +func TestWaitGophers(t *testing.T) { + var gophers = []string{"tom", "peter", "john", "brown"} + + var waitGroup sync.WaitGroup + waitGroup.Add(len(gophers)) + + for i := 0; i < len(gophers); i++ { + go func(wg *sync.WaitGroup, name string) { + sleepyGopherSnore(name) + wg.Done() + }(&waitGroup, gophers[i]) + } + + waitGroup.Wait() + + fmt.Println("All done") +} + +func sleepyGopherSnore(name string) { + fmt.Println(name, ": ... start snore") + time.Sleep(2 * time.Second) + fmt.Println(name, ": ... snore") +} diff --git a/playground/goroutine/deadlock_test.go b/playground/goroutine/deadlock_test.go new file mode 100644 index 0000000..f5ff192 --- /dev/null +++ b/playground/goroutine/deadlock_test.go @@ -0,0 +1,11 @@ +package goroutine + +import "testing" + +// A deadlock happens when a group of goroutines are waiting for each other and none of them is able to proceed. +// The program will get stuck on the channel send operation waiting forever for someone to read the value. +// Go is able to detect situations like this at runtime. +func TestDeadlock(t *testing.T) { + c := make(chan int) + <-c +} diff --git a/playground/goroutine/pipeline_test.go b/playground/goroutine/pipeline_test.go new file mode 100644 index 0000000..4a1bb00 --- /dev/null +++ b/playground/goroutine/pipeline_test.go @@ -0,0 +1,39 @@ +package goroutine + +import ( + "fmt" + "strings" + "testing" +) + +func sourceGopher(downstream chan string) { + for _, v := range []string{"hello world", "a bad apple", "goodbye all"} { + downstream <- v + } + close(downstream) +} + +func filterGopher(upstream, downstream chan string) { + for item := range upstream { + fmt.Println("filter ", item) + + if !strings.Contains(item, "bad") { + downstream <- item + } + } +} + +func printGopher(upstream chan string) { + for item := range upstream { + fmt.Println("print ", item) + } +} + +// Pipeline source->filter->print +func TestPipeline(t *testing.T) { + c0 := make(chan string) + c1 := make(chan string) + go sourceGopher(c0) + go filterGopher(c0, c1) + printGopher(c1) +} diff --git a/playground/http/get_test.go b/playground/http/get_test.go new file mode 100644 index 0000000..df65422 --- /dev/null +++ b/playground/http/get_test.go @@ -0,0 +1,48 @@ +package http + +import ( + "fmt" + "io/ioutil" + "log" + "math/rand" + "net/http" + "sync" + "testing" + "time" +) + +func TestGet(t *testing.T) { + counts := 2 + + var wg sync.WaitGroup + wg.Add(counts) + + for i := 0; i < counts; i++ { + go func() { + defer wg.Done() + getValue() + }() + } + wg.Wait() +} + +func getValue() { + rand.Seed(time.Now().UnixNano()) + x := rand.Intn(10) + var url string + if x > 5 { + url = "http://localhost:48082/api/v1/device/5bae2ef4f37ba14693a5e4fc/command/5bae2ef4f37ba14693a5e4eb" + } else { + url = "http://localhost:48082/api/v1/device/5bae2d1bf37ba14693a5e4e9/command/5bae2d05f37ba14693a5e4e2" + } + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + } + + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(resBody)) +} diff --git a/playground/http/postyamlstring_test.go b/playground/http/postyamlstring_test.go new file mode 100644 index 0000000..ce52571 --- /dev/null +++ b/playground/http/postyamlstring_test.go @@ -0,0 +1,46 @@ +package http + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "testing" +) + +func TestPostYamlString(t *testing.T) { + var filePath = "/Users/bruce/Desktop/HVAC-CoolMasterNet.yml" + var url = "http://localhost:48081/api/v1/deviceprofile/upload" + + // read file to byte + yamlFile, err := ioutil.ReadFile(filePath) + if err != nil { + t.Fatal(err) + } + + fmt.Println(string(yamlFile)) + + // create http post request + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(yamlFile)) + if err != nil { + t.Fatal(err) + } + + // submit request + client := &http.Client{} + res, err := client.Do(req) + if err != nil { + t.Fatal(err) + } + + // check response + fmt.Println("== upload finish ==") + resBody, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + fmt.Println(res.StatusCode) + fmt.Println(res.Header) + res.Body.Close() + fmt.Println(string(resBody)) +} diff --git a/playground/http/upload_test.go b/playground/http/upload_test.go new file mode 100644 index 0000000..0081e10 --- /dev/null +++ b/playground/http/upload_test.go @@ -0,0 +1,63 @@ +package http + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "path/filepath" + "testing" +) + +func TestUploadFormFile(t *testing.T) { + var filePath = "/Users/bruce/Desktop/HVAC-CoolMasterNet.yml" + var url = "http://localhost:48081/api/v1/deviceprofile/uploadfile" + + // Retch file + fmt.Println("Read file: ", filepath.Base(filePath)) + yamlFile, err := ioutil.ReadFile(filePath) + if err != nil { + t.Fatal(err) + } + + // create form data + body := new(bytes.Buffer) + //body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + formFileWriter, err := writer.CreateFormFile("file", filepath.Base(filePath)) + if err != nil { + t.Fatal(err) + } + _, err = io.Copy(formFileWriter, bytes.NewReader(yamlFile)) + if err != nil { + t.Fatal(err) + } + writer.Close() + + // create http post request + req, err := http.NewRequest(http.MethodPost, url, body) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", writer.FormDataContentType()) + + // submit request + client := &http.Client{} + res, err := client.Do(req) + if err != nil { + t.Fatal(err) + } + + // check response + fmt.Println("== upload finish ==") + resBody, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + fmt.Println(res.StatusCode) + fmt.Println(res.Header) + res.Body.Close() + fmt.Println(string(resBody)) +} diff --git a/playground/mocklib/mocks/Robot.go b/playground/mocklib/mocks/Robot.go new file mode 100644 index 0000000..3b4833d --- /dev/null +++ b/playground/mocklib/mocks/Robot.go @@ -0,0 +1,15 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Robot is an autogenerated mock type for the Robot type +type Robot struct { + mock.Mock +} + +// SayHi provides a mock function with given fields: +func (_m *Robot) SayHi() { + _m.Called() +} diff --git a/playground/mocklib/robot.go b/playground/mocklib/robot.go new file mode 100644 index 0000000..b3e0cc1 --- /dev/null +++ b/playground/mocklib/robot.go @@ -0,0 +1,45 @@ +package mocklib + +import "fmt" + +// Robot +type Robot interface { + SayHi() +} + +// ServiceRobot is kind of Robot can offer services +type ServiceRobot struct { +} + +func (robot *ServiceRobot) SayHi() { + fmt.Println("Hi, I'm service robot") +} + +// IndustrialRobot is kind of Robot can do some jobs +type IndustrialRobot struct { +} + +func (robot *IndustrialRobot) SayHi() { + fmt.Println("Hi, I'm industrial robot") +} + +func StartRobots() { + robots := initializeRobots() + makeRobotsSayHi(robots) +} + +// initialize all robots +func initializeRobots() []Robot { + robots := []Robot{ + &ServiceRobot{}, + &IndustrialRobot{}, + } + return robots +} + +// makeRobotsSayHi is used for making robots say hi +func makeRobotsSayHi(robots []Robot) { + for _, robot := range robots { + robot.SayHi() + } +} diff --git a/playground/mocklib/robot_test.go b/playground/mocklib/robot_test.go new file mode 100644 index 0000000..d02385e --- /dev/null +++ b/playground/mocklib/robot_test.go @@ -0,0 +1,32 @@ +package mocklib + +import ( + "github.com/weichou1229/go-patterns/playground/mocklib/mocks" + "testing" +) + +func TestStartRobots(t *testing.T) { + StartRobots() +} + +func TestMakeRobotsSayHi(t *testing.T) { + // create an instance of our test object + mockRobotA := new(mocks.Robot) + mockRobotB := new(mocks.Robot) + + // setup expectations + mockRobotA.On("SayHi").Return(nil, nil) + mockRobotB.On("SayHi").Return(nil, nil) + + robots := []Robot{ + mockRobotA, + mockRobotB, + } + + // Act + makeRobotsSayHi(robots) + + // Assert that the expectations were met + mockRobotA.AssertExpectations(t) + mockRobotB.AssertExpectations(t) +} diff --git a/playground/panic/trypanic.go b/playground/panic/trypanic.go new file mode 100644 index 0000000..2a0cb25 --- /dev/null +++ b/playground/panic/trypanic.go @@ -0,0 +1,10 @@ +package trypanic + +import ( + "fmt" +) + +func Try() { + var test *string + fmt.Println(*test) +} diff --git a/playground/parse/parseInt_test.go b/playground/parse/parseInt_test.go new file mode 100644 index 0000000..4cd44eb --- /dev/null +++ b/playground/parse/parseInt_test.go @@ -0,0 +1,14 @@ +package parse + +import ( + "fmt" + "strconv" + "testing" +) + +func TestParseInt(t *testing.T) { + var _, err = strconv.ParseInt("127", 0, 8) + if err != nil { + fmt.Println(err) + } +} diff --git a/playground/pointer/pointer_test.go b/playground/pointer/pointer_test.go new file mode 100644 index 0000000..53593ca --- /dev/null +++ b/playground/pointer/pointer_test.go @@ -0,0 +1,26 @@ +package pointer + +import ( + "fmt" + "testing" +) + +func TestBasic(t *testing.T) { + answer := 42 + fmt.Println(&answer) // & is address operator + + address := &answer + fmt.Println(*address) // * is dereferencing, which providers the value that a memory address refers to. + fmt.Printf("address is a %T \n", address) // print the pointer type + + var address2 *int // declare a pointer + address2 = address // address2 can store some pinter type + fmt.Println(*address2) + +} + +func TestPointer(t *testing.T) { + var test *string = new(string) + *test = "123" + fmt.Println(test) +} diff --git a/playground/singleton/internal/singleton.go b/playground/singleton/internal/singleton.go new file mode 100644 index 0000000..804794c --- /dev/null +++ b/playground/singleton/internal/singleton.go @@ -0,0 +1,27 @@ +package internal + +import ( + "fmt" + "sync" +) + +// singleton is private struct, it should be created and fetched by GetSingletonObject func +type singleton struct { +} + +func (singleton) SayHi() { + fmt.Println("Hi!") +} + +var ( + once sync.Once + instance singleton +) + +func GetSingletonObject() singleton { + once.Do(func() { + instance = singleton{} + }) + + return instance +} diff --git a/playground/singleton/main.go b/playground/singleton/main.go new file mode 100644 index 0000000..a1ec7ad --- /dev/null +++ b/playground/singleton/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/weichou1229/go-patterns/playground/singleton/internal" +) + +func main() { + var s = internal.GetSingletonObject() + s.SayHi() +} diff --git a/playground/syncmap/syncmap_test.go b/playground/syncmap/syncmap_test.go new file mode 100644 index 0000000..b53fb59 --- /dev/null +++ b/playground/syncmap/syncmap_test.go @@ -0,0 +1,52 @@ +package syncmap + +import ( + "fmt" + "sync" + "testing" +) + +type Order struct { + Id int +} + +func TestSync(t *testing.T) { + var waitGroup sync.WaitGroup + waitGroup.Add(10) + var cache sync.Map + + for i := 0; i < 10; i++ { + go func() { + cache.Store("test", &Order{}) + order, _ := cache.Load("test") + o := order.(*Order) + fmt.Println(o) + waitGroup.Done() + }() + } + waitGroup.Wait() +} + +func TestSync2(t *testing.T) { + var cache sync.Map + + cache.Store("test", nil) + + if order, ok := cache.Load("test"); ok && order != nil { + fmt.Println(order) + } else { + fmt.Println("not exist") + } +} + +func TestSync3(t *testing.T) { + var cache sync.Map + orders := make([]Order, 2) + + cache.Store("test2", orders[0]) + cache.Store("test", orders[0]) + + order, ok := cache.Load("test") + fmt.Println(ok, order) + +} diff --git a/playground/xml/2018Q1.xml b/playground/xml/2018Q1.xml new file mode 100755 index 0000000..d7376d8 --- /dev/null +++ b/playground/xml/2018Q1.xml @@ -0,0 +1,4089 @@ + + + + + 2408 + + + 2018-05-09 + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2017-03-31 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2017-03-31 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2017-01-01 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2017-01-01 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2018-03-31 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2018-03-31 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:TotalEquityMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:NoncontrollingInterestsMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:EquityAttributableToFomerOwnerOfBusinessCombinationUnderCommonControl + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:EquityAttributableToOwnersOfParentMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:TreasurySharesMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:OtherEquityInterestMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:Others-OtherEquityInterestMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:EquityRelatedToNoncurrentAssetsOrDisposalGroupsClassifiedAsHeldForDistributionToOwnersMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:AmountRecognisedInOtherComprehensiveIncomeAndAccumulatedInEquityRelatingToNoncurrentAssetsOrDisposalGroupsHeldForSaleMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:RevaluationSurplusMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfRemeasurementsOfDefinedBenefitPlansMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfChangeInFairValueOfFinancialLiabilityAttributableToChangeInCreditRiskOfLiabilityMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:GainsLossesOnEffectivePortionOfHedgesOfNetInvestmentsInForeignOperationsMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfCashFlowHedgesMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfGainsAndLossesOnRemeasuringAvailableforsaleFinancialAssetsMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfGainsAndLossesOnFinancialAssetsMeasuredAtFairValueThroughOtherComprehensiveIncomeMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:ReserveOfExchangeDifferencesOnTranslationMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:RetainedEarningsMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:UnappropriatedRetainedEarningsAccumulatedDeficitMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:SpecialReserveMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:StatutoryReserveMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:CapitalReserveMember + + + + + 2408 + + + 2018-01-01 + + + ifrs-full:IssuedCapitalMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:Other-ShareCapitalMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:StockDividendToBeDistributedMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:AdvanceReceiptsForShareCapitalMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:CertificateOfEntitlementToNewSharesFromConvertibleBondMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:PreferenceShareMember + + + + + 2408 + + + 2018-01-01 + + + tifrs-es:OrdinaryShareMember + + + + + 2408 + + + 2017-12-31 + + + + + 2408 + + + 2017-01-01 + 2017-03-31 + + + + + 2408 + + + 2017-03-31 + + + + + 2408 + + + 2018-01-01 + 2018-03-31 + + + + + 2408 + + + 2018-03-31 + + + + iso4217:TWD + + + xbrli:shares + + + + + iso4217:TWD + + + xbrli:shares + + + + + xbrli:pure + + 2018 + 1 + Financial report (general) + Consolidated report + Listed company + Commercial and industrial + 50196810000 + 33768677000 + 20299894000 + 11044995000 + 8525608000 + 5782714000 + 858673000 + 11601416000 + 1454256000 + 0 + 0 + 0 + 7868893000 + 6888530000 + 4656170000 + 1996194000 + 1622096000 + 1430620000 + 71965565000 + 62406327000 + 33623654000 + 0 + 0 + 50728048000 + 84607717000 + 86241880000 + 71886199000 + 102331000 + 136550000 + 238424000 + 859732000 + 922559000 + 846975000 + 1032293000 + 1071986000 + 1602634000 + 1003224000 + 1043501000 + 1278815000 + 1003224000 + 1043501000 + 1278815000 + 29069000 + 28485000 + 323819000 + 86602073000 + 88372975000 + 125302280000 + 158567638000 + 150779302000 + 158925934000 + 0 + 2238441000 + 1439801000 + 3195934000 + 3072987000 + 5328595000 + 327777000 + 299746000 + 192637000 + 7167115000 + 6297730000 + 4039590000 + 995508000 + 1065854000 + 10900041000 + 1713782000 + 1726392000 + 2088872000 + 1617000 + 1954000 + 7187658000 + 0 + 0 + 7186625000 + 0 + 0 + 7186625000 + 1617000 + 1954000 + 1033000 + 13401733000 + 14703104000 + 31177194000 + 0 + 3286711000 + 14002436000 + 0 + 0 + 12776825000 + 553000 + 63699000 + 3264513000 + 635359000 + 610600000 + 567206000 + 525020000 + 525797000 + 449279000 + 110339000 + 84803000 + 117927000 + 635912000 + 3961010000 + 30610980000 + 14037645000 + 18664114000 + 61788174000 + 30028820000 + 29639382000 + 27485658000 + 567359000 + 223958000 + 0 + 30596179000 + 29863340000 + 27485658000 + 29654480000 + 25150157000 + 9852246000 + 29654480000 + 25150157000 + 9852246000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2192903000 + 2127034000 + 1782354000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3300000 + 31847383000 + 27277191000 + 11637900000 + 5164057000 + 5164057000 + 2791929000 + 0 + 0 + 4570000 + 76961794000 + 69734440000 + 39571384000 + 82125851000 + 74898497000 + 42367883000 + -39420000 + -39163000 + 15883901000 + 0 + 0 + 347533000 + 144529993000 + 131999865000 + 97027809000 + 0 + 0 + 0 + 0 + 115323000 + 109951000 + 144529993000 + 132115188000 + 97137760000 + 158567638000 + 150779302000 + 158925934000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 687558 + 18797439000 + 12230574000 + 9056761000 + 7330057000 + 9740678000 + 4900517000 + 9740678000 + 4900517000 + 195492000 + 173460000 + 350091000 + 347654000 + 876079000 + 526763000 + 1421662000 + 1047877000 + 8319016000 + 3852640000 + 235627000 + 88313000 + -1322009000 + -532488000 + 5298000 + 121997000 + -1091680000 + -566172000 + 7227336000 + 3286468000 + 1181000 + 3778000 + 7226155000 + 3282690000 + 7226155000 + 3282690000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -424000 + 0 + 424000 + 0 + -257000 + -20404000 + 0 + 9776747000 + 0 + 1661543000 + -257000 + 8094800000 + 167000 + 8094800000 + 7226322000 + 11377490000 + 7226930000 + 3275298000 + -775000 + 7392000 + 7227097000 + 11370098000 + -775000 + 7392000 + 2.39 + 1.19 + 2.39 + 1.19 + 2.31 + 1.01 + 2.31 + 1.01 + 7227336000 + 3286468000 + 7227336000 + 3286468000 + 2882097000 + 1534865000 + 35647000 + 70406000 + 281107000 + 262158000 + 5298000 + 121997000 + -235628000 + -88313000 + 65869000 + 114893000 + 0 + -70684000 + -46000 + -24000 + 0 + -770000 + -497000 + 0 + -105403000 + 11677000 + 161805000 + -206229000 + 0 + -63542000 + 3090249000 + 1686434000 + -2579688000 + -87476000 + 158843000 + 519652000 + -1117269000 + 193322000 + -377265000 + 83662000 + -3915379000 + 709160000 + -523136000 + 0 + 273544000 + 33864000 + 1667694000 + 120650000 + -337000 + -235302000 + -777000 + -4234000 + 916000 + -10450000 + 1417904000 + -95472000 + -2497475000 + 613688000 + 592774000 + 2300122000 + 7820110000 + 5586590000 + 145040000 + 26698000 + 0 + 0 + -292000 + -106345000 + -21368000 + -8823000 + 7943490000 + 5498120000 + 0 + 2000771000 + -85937000 + 0 + -1940662000 + -6147471000 + 46000 + 80000 + -1501000 + -1899000 + 10616574000 + 0 + 107333000 + 107332000 + -1278000 + 72297000 + 8694575000 + -3968890000 + 0 + 15681000000 + 0 + -3000000000 + 25316000 + 30494000 + 4530000 + -2696964000 + 0 + -4138000 + 0 + 0 + 0 + 230000 + 29846000 + 10010622000 + -239778000 + -341590000 + 16428133000 + 11198262000 + 33768677000 + 9101632000 + 50196810000 + 20299894000 + 29639382000 + 0 + 223958000 + 0 + 0 + 0 + 29863340000 + 27277191000 + 5164057000 + 0 + 69734440000 + 74898497000 + -39163000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -39163000 + 0 + 131999865000 + 0 + 115323000 + 132115188000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 29639382000 + 0 + 223958000 + 0 + 0 + 0 + 29863340000 + 27277191000 + 5164057000 + 0 + 69734440000 + 74898497000 + -39163000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -39163000 + 0 + 131999865000 + 0 + 115323000 + 132115188000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 7226930000 + 7226930000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 7226930000 + 0 + -775000 + 7226155000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 424000 + 424000 + -257000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -257000 + 0 + 167000 + 0 + 0 + 167000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 7227354000 + 7227354000 + -257000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -257000 + 0 + 7227097000 + 0 + -775000 + 7226322000 + 165480000 + 0 + 567359000 + 0 + 0 + 0 + 732839000 + 4504323000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 5237162000 + 0 + 0 + 5237162000 + 223958000 + 0 + -223958000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -114548000 + -114548000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 65869000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 65869000 + 0 + 0 + 65869000 + 389438000 + 0 + 343401000 + 0 + 0 + 0 + 732839000 + 4570192000 + 0 + 0 + 7227354000 + 7227354000 + -257000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -257000 + 0 + 12530128000 + 0 + -115323000 + 12414805000 + 30028820000 + 0 + 567359000 + 0 + 0 + 0 + 30596179000 + 31847383000 + 5164057000 + 0 + 76961794000 + 82125851000 + -39420000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -39420000 + 0 + 144529993000 + 0 + 0 + 144529993000 + 27485658000 + 0 + 0 + 0 + 0 + 0 + 27485658000 + 11523007000 + 2791929000 + 4570000 + 36296086000 + 39092585000 + -16846000 + 0 + 7805947000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 7789101000 + -347533000 + 85542818000 + 0 + 102329000 + 85645147000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 27485658000 + 0 + 0 + 0 + 0 + 0 + 27485658000 + 11523007000 + 2791929000 + 4570000 + 36296086000 + 39092585000 + -16846000 + 0 + 7805947000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 7789101000 + -347533000 + 85542818000 + 0 + 102329000 + 85645147000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3275298000 + 3275298000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3275298000 + 0 + 7392000 + 3282690000 + -20404000 + 0 + 8115204000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8094800000 + 0 + 8094800000 + 0 + 0 + 8094800000 + 3275298000 + 3275298000 + -20404000 + 0 + 8115204000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8094800000 + 0 + 11370098000 + 0 + 7392000 + 11377490000 + 0 + 0 + 0 + 0 + 230000 + 230000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 114893000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 114893000 + 0 + 0 + 114893000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 114893000 + 0 + 0 + 3275298000 + 3275298000 + -20404000 + 0 + 8115204000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8094800000 + 0 + 11484991000 + 0 + 7622000 + 11492613000 + 27485658000 + 0 + 0 + 0 + 0 + 0 + 27485658000 + 11637900000 + 2791929000 + 4570000 + 39571384000 + 42367883000 + -37250000 + 0 + 15921151000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 15883901000 + -347533000 + 97027809000 + 0 + 109951000 + 97137760000 + 2018-05-09 + Y + Y + Y + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 3840102000 + -73176000 + 0 + 0 + + + + + + + + + + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 0.0000 + 0.5356 + 0.5357 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + + 1.0000 + 1.0000 + 1.0000 + + + + + + + 2390000 + 3577000 + 11978000 + + + + + 11051779000 + 8530890000 + 5779819000 + + + + + -9174000 + -8859000 + -9083000 + + + + 11044995000 + 8525608000 + 5782714000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 6023000 + + + + 0 + 6023000 + + + 15104000 + 12314000 + + + + + 419527000 + 269562000 + + + + + 22470000 + 8250000 + + + + 457101000 + 290126000 + + + + 5597000 + 4750000 + 3936000 + + + + + + 315826000 + 290134000 + 186508000 + + + + + + 6354000 + 4862000 + 2193000 + + + + + + 0 + 0 + 0 + + + + + + 891118000 + 889629000 + 703498000 + + + + 1218895000 + 1189375000 + 896135000 + + + 391000 + 2489000 + + + + + 2111000 + 41176000 + + + + 2502000 + 43665000 + + + 0 + 0 + 8000000000 + + + + + 8322000 + 2282000 + 0 + + + + + 0 + 5934000 + 0 + + + + + 4624000 + 0 + 0 + + + + + 0 + 200000 + 2045308000 + + + + 12946000 + 8416000 + 10045308000 + 12192000 + 11918000 + 0 + 0 + 0 + 0 + 0 + 0 + 1694000 + 3001000 + 13886000 + 14919000 + + 0 + + + + + + 1354923000 + + 0.0721 + + + + + 0 + + + + + + 1060546000 + + 0.0564 + + + + + 0 + + + + + + 1103852000 + + 0.0587 + + + + + 0 + + + + + + 1075876000 + + 0.0068 + + + + + 0 + + + + + + 950444000 + + 0.0060 + + + + + 0 + + + + + + 1313134000 + + 0.0083 + + + + + + + + + + + 20392000 + 20392000 + + + 2000 + 1.0000 + 107754000 + + 1067000 + 1067000 + + + + + + + + + + + 36005000 + 36005000 + + + 0 + 1.0000 + 130032000 + + 3262000 + 3262000 + + + + + + + + + + + 325348000 + 325348000 + + + 2935000 + 1.0000 + 43734000 + + 43000 + 43000 + + + + + + + + + + + 66271000 + 66271000 + + + 20000 + 1.0000 + 55483000 + + 12733000 + 12733000 + + + + + + + + + + + 20161000 + 20161000 + + + 1000 + 1.0000 + 84358000 + + -88612000 + -88612000 + + + + + + + + + + + 0 + 21246000 + + + 0 + 0.0000 + 0 + + -1669000 + -894000 + + + + + + + + + + + 30056000 + 30056000 + + + 0 + 1.0000 + 76947000 + + 17125000 + 17125000 + + + + + + + + 28683000 + + 28683000 + + 0 + 0 + + 28683000 + -4830000 + 1.0000 + -4830000 + 2587000 + 0 + + + + + + 28683000 + 28683000 + 86717996000 + + + + 202732000 + 48050000 + 32895000 + 40263000 + 235627000 + 88313000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 235627000 + 88313000 + 46000 + 24000 + -1178033000 + -574814000 + -281107000 + -262158000 + 105403000 + -11677000 + 105403000 + -11677000 + 31682000 + 316137000 + -1322009000 + -532488000 + 5250000 + 121990000 + 48000 + 7000 + 5298000 + 121997000 + + + diff --git a/playground/xml/xml_test.go b/playground/xml/xml_test.go new file mode 100644 index 0000000..26b98f7 --- /dev/null +++ b/playground/xml/xml_test.go @@ -0,0 +1,63 @@ +package xml + +import ( + "fmt" + xj "github.com/basgys/goxml2json" + "github.com/buger/jsonparser" + "os" + "testing" +) + +type Person struct { + Name string `xml:"name"` +} + +func TestParse(t *testing.T) { + xmlFile, err := os.Open("2018Q1.xml") + if err != nil { + fmt.Println(err) + return + } + defer xmlFile.Close() + json, err := xj.Convert(xmlFile) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(json.String()) + + //err = jsonparser.ObjectEach(json.Bytes(), objectEach,"xbrl") + //if err != nil { + // fmt.Println(err) + // return + //} + + // 營業收入 + var revenue string + _, err = jsonparser.ArrayEach(json.Bytes(), func(value []byte, dataType jsonparser.ValueType, offset int, err error) { + revenue, err = jsonparser.GetString(value, "#content") + fmt.Println(revenue) + }, "xbrl", "Revenue") + if err != nil { + fmt.Println(err) + return + } +} + +func parse(b []byte) { + err := jsonparser.ObjectEach(b, objectEach, "xbrl") + if err != nil { + fmt.Println(err) + return + } +} + +func objectEach(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { + fmt.Printf("[Key]: [%s]\n Value: '%s'\n Type: %s\n", string(key), string(value), dataType) + return nil +} + +func arrayEach(value []byte, dataType jsonparser.ValueType, offset int, err error) { + fmt.Printf("Array Value: '%s'\n Type: %s\n", string(value), dataType) +}