-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdoc.go
165 lines (124 loc) · 5.91 KB
/
doc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
Package constant provides an interface for creating and storing constants in a key based tree structure.
If available, constants are read from the environment, to provide dynamic configuration.
Package constant also provides a templating system to create constants based of the values of other constants.
Template
Package constant provides a template system using text/template (https://golang.org/pkg/text/template/) to allow nodes to be expressed as a combintation of other nodes in the same context.
The following methods are available to use in a node.
{{ const "path1" ["path2" ...] }}
Returns the value of of another node in the same context as defined by
path1[, path2 ...]. Self reference is not allowed and returns an empty string.
Nodes that don't exist return an empty string.
Example:
`{{ const "host" }}:{{ const "port" }}`
If host=`localhost` and port=`3306` then the above template would return
`localhost:3306`.
Caution:
Although there is a check in place to test if a node references itself,
there is no check for cyclic dependancy. If a cyclic dependancy is
created then the program will enter an infinite loop.
{{ list }}
Returns a sorted slice of all nodes in the context except itself.
Example:
`{{ range list }}{{ . }}={{ const . }}; {{ end }}`
If host=`localhost` and port=`3306` then the above template would return
`host=localhost; port=3306; `.
{{ isset "path1" ["path2" ...] }}
Returns whether or not a node as defined by path1[, path2 ...] is in the
current context.
Example:
`{{ const "protocol" }}://{{ const "domain" }}{{if isset "port"}}:{{ const "port" }}{{end}}/{{ const "page" }}`
If protocol=`http`, domain=`localhost` and page=`index.html` then the
above template would return `http://localhost/index.html`.
Or if the same constants are set as well as port=`8080` then the above
template would return `http://localhost:8080/index.html`.
Template Context
The context for a node includes the context's root node and all of its children recursively.
The root node for a context is the parent of the node.
Therefore the context for a node includes itself, its parent node, its parent's child nodes (siblings of the original node) and all the recursive children.
A node is excluded from the context if its default value is nil.
Other nodes in the same context are referenced by their path relative to the root of the context.
This starts with the root of the context which is referenced as an empty string.
Siblings are referenced by their name ("sibling name").
Recursive children are referenced by the names of their parents followed by their name ("sibling name", "recursive child").
For example if the folling tree structure is created
___ name: MYAPP ___
/ value: nil \
/ | \
name: LOG name: RUNTIME name: DATABASE
value: nil value: `dev` value: `true`
/ | / | \
name: LEVEL name: FILE name: HOST name: PORT name: ADDRESS
value: 5 value: `stdout` value: `localhost` value: 3306 value: ?
|
name: PROVIDER
value: `internal`
then 'ADDRESS' could be set to and would return
`{{ const "" }}` -> `true` (value of parent)
`{{ const "HOST" }}` -> `localhost`
`{{ const "HOST" "PROVIDER" }}` -> `internal`
`{{ const "PORT" }}` -> `true`
`{{ const "ADDRESS" }}` -> `` (self reference not allowed)
`{{ list }}` -> `[ HOST HOST_PROVIDER PORT]` (includes an empty string at the start)
`{{ isset "HOST" }}` -> `true`
`{{ isset "SOMETHING" }}` -> `false`
Example
In the following example the tree from the above section (Template Context) is created.
In this example 'ADDRESS' is set by default to equal `HOST + ":" + PORT`.
After creation, HOST is updated via an envionment variable which, in turn, also updates the value of ADDRESS.
package main
import (
"fmt"
"github.com/JamesStewy/constant"
"os"
)
var tree *constant.Node
func main() {
// Create new tree for my app
tree = constant.NewTree("MYAPP", "_")
// Create LOG node
tree.New("LOG", nil)
tree.Node("LOG").New("LEVEL", 5)
tree.Node("LOG").New("FILE", "stdout")
// Create RUNTIME node
tree.New("RUNTIME", "dev")
// Create DATABASE node (using alternate method to LOG node)
mysql_tree, _ := tree.New("DATABASE", true)
mysql_tree.New("HOST", "localhost")
mysql_tree.Node("HOST").New("PROVIDER", "internal")
mysql_tree.New("PORT", 3306)
// Set ADDRESS to be equal to HOST + ":" + PORT
mysql_tree.New("ADDRESS", `{{ const "HOST" }}:{{ const "PORT" }}`)
display_pool()
// Update the MySQL host
os.Setenv("MYAPP_DATABASE_HOST", "mydomain.com")
fmt.Println("\nChanged MYAPP_DATABASE_HOST to mydomain.com\n")
display_pool()
}
func display_pool() {
// Loop through each constant in the pool and display its value
for _, node := range tree.Nodes() {
// Call node.Str(name) to retrieve the node's value
fmt.Printf("%s=%s\n", node.FullName(), node.Str())
}
}
The above example returns:
MYAPP_LOG_LEVEL=5
MYAPP_LOG_FILE=stdout
MYAPP_RUNTIME=dev
MYAPP_DATABASE=true
MYAPP_DATABASE_HOST=localhost
MYAPP_DATABASE_HOST_PROVIDER=internal
MYAPP_DATABASE_PORT=3306
MYAPP_DATABASE_ADDRESS=localhost:3306
Changed MYAPP_DATABASE_HOST to mydomain.com
MYAPP_LOG_LEVEL=5
MYAPP_LOG_FILE=stdout
MYAPP_RUNTIME=dev
MYAPP_DATABASE=true
MYAPP_DATABASE_HOST=mydomain.com
MYAPP_DATABASE_HOST_PROVIDER=internal
MYAPP_DATABASE_PORT=3306
MYAPP_DATABASE_ADDRESS=mydomain.com:3306
*/
package constant