The Go standard library, implemented in Javascript
BSD-3-CLAUSE License
This is an attempt to implement useful features of the Go standard library in Javascript.
This is written in plain Javascript and doesn't have any dependencies so you should be able to run it in lots of places.
We check types on the inputs to a function and always try to return the correct types from a function.
Go strings are JS strings, except JS strings are assumed to be encoded as UTF-16, which means that the encoding behavior needs to change in some circumstances.
Functions that take a rune in Go take an integer in Javascript.
We use custom int64
and uint64
types due to Javascript's lack of precision
for these integers. Several functions return them, for example a time.Duration
stores an int64 internally. The downside is that normal math operators - -
,
+
, *
, /
, don't work with these types. Instead you have to use custom
operators:
add
- add another Int64/Uint64.addn
- add an integersub
- sub another Int64/Uint64subn
- sub another integermul
/muln
- multiplicationmod
/modn
- modulo arithmeticlt
/ltn
- less thanlte
/lten
- less than or equal toeq
/eqn
- equal togt
/gtn
- greater thangte
/gten
- greater than or equal toEach of these will throw if you pass an object that has the wrong type, e.g if
you pass an Int64 object to addn
. This should help you verify that your code
is doing the thing you expect it to, and failing when it does something you
don't expect it to.
time.Duration
objects support all of these functions. If a Go function
accepts an int64 or a uint64, those should be converted to the equivalent
Int64
/Uint64
objects before using this library. If a Go function accepts an
int
, we use normal Javascript numbers.
Int64
objects can only do operations with other Int64
objects. To convert
a Uint64
to an Int64
, call toSigned()
, and call .toUnsigned()
in the
opposite direction.
Run make test
. The tests use the most recent versions of mocha
and should
,
as well as eslint
for validation.
Copy the source code directly to your project. You should inspect the source of the project and see if it makes sense for you. You may only need a single method, in which case you should just copy that into your source tree directly.
To require a module, require the index.js
file in the package. So to import
the time
package:
const time = require('./gostdjs/time/index.js');
Installation via NPM encourages bloat and discourages people from inspecting the source code to see if the tool a) does what they want and b) does not do what they don't want. If this makes it harder for you to install - good! It should be more expensive in time and effort to install third party packages.
I will tag new releases via Git, along with a change log, and you can use Git and the Github compare tool to diff changes between releases.
For now performance is a secondary goal to correctness. A lot of the optimizations present in the Go standard library around e.g. short vs long strings are missing here.
Functions that don't use I/O and return an error as the last parameter should
instead throw an error. Use internal.throwSystem
in catch handlers to
distinguish between system errors (type and syntax errors) and user errors.
To convert between strings and their ASCII character equivalents, do
'a'.charCodeAt(0)
. Unfortunately you can't do math between uint8
types and
bytes. To get a Unicode code point at a character, do 'uchar'.codePointAt(0)
,
which may yield a number larger than 256.
To convert tests, switch something like this:
if d1 != d2 {
t.Errorf("%d != %d", d1, d2)
}
to:
d1.should.equal(d2, util.format("%d != %d", d1, d2))
Note util.format does not line up exactly with fmt.Printf parameters, so you might need to massage it a little bit.