
如何将 COBOL 自动转换为 Go 语言
尽管 COBOL 可被视为一种传统语言,但仍有数十亿行 COBOL 在生产中使用。对这些运行和维护成本高昂的系统进行现代化改造是一项挑战。解决这一问题的方法之一是 COBOL 到 Go 的转译器,我想在本文中介绍它 .
COBOL
COBOL 首次出现于 1959 年,是一种专为商业用途设计的编译语言。如今,主要是大型金融机构和政府机构在生产中使用 COBOL 系统。它通常部署在大型计算机上,例如 IBM 公司运行 z/OS 的 Z 大型机。虽然现在也有面向对象的功能,但 COBOL 主要是一种过程式和命令式语言。 这是一个简单的 COBOL hello word 程序:
hello.cob
* Sample COBOL program
IDENTIFICATION DIVISION.
PROGRAM-ID. hello.
PROCEDURE DIVISION.
DISPLAY "Hello, world!".
STOP RUN.
你可以在自己的计算机上试用,例如使用 GnuCOBOL。 运行以下编译命令进行尝试:
$ cobc -x hello.cob
$ ./hello
Go
Go 是一种静态类型的编译高级编程语言,由 Robert Griesemer、Rob Pike 和 Ken Thompson 在 Google 设计。 它的优点是对新开发人员来说入门门槛低,而且是一种快速执行的编译语言。 因此,在尝试对传统 COBOL 应用程序进行现代化时,它是一个不错的选择。Go 源代码即使对刚接触 Go 的程序员来说也很容易理解。 这是一个优势,因为 COBOL 软件开发人员的市场具有挑战性,我将在下一节中介绍。
COBOL程序员的市场
许多使用 COBOL 运行系统的大公司都在努力吸引能够维护这些系统的程序员。COBOL 软件开发人员的平均年龄很高,而愿意学习 COBOL 的年轻开发人员却很少。 这对那些拥有数十亿行 COBOL 生产系统的公司来说是一个风险。因此,Enno Richter 开发的 COBOL-to-Go 移植解决方案就派上了用场。
COBOL-to-Go
转换器 资深 COBOL 程序员Enno Richter 拥有数十年(50 年)的 COBOL 编程经验,他开发了一个名为 COBOL-to-Go 的 COBOL 转 Go 转换器。该转译器由一个较早的 RPG-to-COBOL 项目演变而来。 它支持 COBOL-85 标准,但也可根据需要添加较新 COBOL 标准的功能。 其优点之一是生成的 Go 代码易于阅读且结构清晰。不需要运行时系统,因此生成的 Go 代码与 COBOL-to-Go 系统保持独立。Go 可编译到许多操作系统,因此 COBOL 程序可在潜在的许多操作系统上运行。
生成的 Go 代码的所有权利归 COBOL 代码版权所有者所有。 市场上有其他 COBOL 转译器,如 COBOL 到 Java 的转译器,但 Enno Richter 声称他的 Go 转译器的结果更容易理解和维护。 ## 示例代码 以下代码段左侧显示 COBOL 代码,右侧显示转译后的 Go 代码。您可能需要水平滚动才能看到生成的 Go 代码:
* :00190: // 00190: *
*----------------------------------------------------------------* :00191: // 00191: *----------------------------------------------------------------
**------* *-----------------------------------------------------** :00192: // 00192: **------* *-----------------------------------------------------*
** 30 * * P R O G R A M M A B L A U F ** :00193: // 00193: ** 30 * * P R O G R A M M A B L A U F *
**------* *-----------------------------------------------------** :00194: // 00194: **------* *-----------------------------------------------------*
PROCEDURE DIVISION. :00195:
**---------------------------------------------------------------* :00196: // 00196: **---------------------------------------------------------------
** V e r a r b e i t u n g * :00197: // 00197: ** V e r a r b e i t u n g
**---------------------------------------------------------------* :00198: // 00198: **---------------------------------------------------------------
DISPLAY "Test_02400_START --------". :00199: erse.DISlx(&DIS, "Test_02400_START --------") // COBZEI:00199
ersestr1 = erse.DISout(fDISPLAY, &DIS, " ") // COBZEI:00199
* :00200: // 00200: *
* :00201: // 00201: *
**-----------------------------------------------------------* :00202: // 00202: **-----------------------------------------------------------*
** IF LITERAL --- NUMERISCH (Struktur) * :00203: // 00203: ** IF LITERAL --- NUMERISCH (Struktur) *
**-----------------------------------------------------------* :00204: // 00204: **-----------------------------------------------------------*
* IF 12 > BBB-8 :00205: // 00205: * IF 12 > BBB-8
* MOVE SPACE TO BBB-1 :00206: // 00206: * MOVE SPACE TO BBB-1
* END-IF. :00207: // 00207: * END-IF.
* :00208: // 00208: *
* :00209: // 00209: *
**-----------------------------------------------------------* :00210: // 00210: **-----------------------------------------------------------*
** IF NUMERISCH (Struktur) --- LITERAL * :00211: // 00211: ** IF NUMERISCH (Struktur) --- LITERAL *
**-----------------------------------------------------------* :00212: // 00212: **-----------------------------------------------------------*
* IF BBB-8 > 12 :00213: // 00213: * IF BBB-8 > 12
* MOVE SPACE TO BBB-1 :00214: // 00214: * MOVE SPACE TO BBB-1
* END-IF. :00215: // 00215: * END-IF.
* :00216: // 00216: *
* :00217: // 00217: *
**-----------------------------------------------------------* :00218: // 00218: **-----------------------------------------------------------*
** IF LITERAL --- NUMERISCH (Nativ) * :00219: // 00219: ** IF LITERAL --- NUMERISCH (Nativ) *
**-----------------------------------------------------------* :00220: // 00220: **-----------------------------------------------------------*
* IF 12 > Z3 :00221: // 00221: * IF 12 > Z3
* MOVE SPACE TO BBB-1 :00222: // 00222: * MOVE SPACE TO BBB-1
* END-IF. :00223: // 00223: * END-IF.
* :00224: // 00224: *
* :00225: // 00225: *
**-----------------------------------------------------------* :00226: // 00226: **-----------------------------------------------------------*
** IF NUMERISCH (Nativ) --- LITERAL * :00227: // 00227: ** IF NUMERISCH (Nativ) --- LITERAL *
**-----------------------------------------------------------* :00228: // 00228: **-----------------------------------------------------------*
* IF Z3 > 12 :00229: // 00229: * IF Z3 > 12
* MOVE SPACE TO BBB-1 :00230: // 00230: * MOVE SPACE TO BBB-1
* END-IF. :00231: // 00231: * END-IF.
* :00232: // 00232: *
* :00233: // 00233: *
**-----------------------------------------------------------* :00234: // 00234: **-----------------------------------------------------------*
** IF NUMERISCH (Struktur) ---- NUMERISCH (Struktur) * :00235: // 00235: ** IF NUMERISCH (Struktur) ---- NUMERISCH (Struktur) *
**-----------------------------------------------------------* :00236: // 00236: **-----------------------------------------------------------*
IF BBB_8 > HHH :00237: if erse.IFNCVCV(&BBB_8_cv, ">", &HHH_cv) {
MOVE SPACE TO BBB_1 :00238: erse.MVACVLI(&BBB_1_cv,"SPACE") // COBZEI:00238
END-IF. :00239: } // ENDIF
* :00240: // 00240: *
* :00241: // 00241: *
**-----------------------------------------------------------* :00242: // 00242: **-----------------------------------------------------------*
** P R O G R A M M - E N D E * :00243: // 00243: ** P R O G R A M M - E N D E *
**-----------------------------------------------------------* :00244: // 00244: **-----------------------------------------------------------*
DISPLAY "Test_02400 ENDE -------------". :00245: erse.DISlx(&DIS, "Test_02400 ENDE -------------") // COBZEI:00245
ersestr1 = erse.DISout(fDISPLAY, &DIS, " ") // COBZEI:00245
STOP RUN. :00246: //---------------------------------------------------------------
// STOP-RUN (Ende der Programmlogik)
//---------------------------------------------------------------
os.Exit(0)
**--------------------------------------------------------------** :00247: // 00247: **--------------------------------------------------------------*
** Ende : ** :00248: // 00248: ** Ende : *
** ~~Projekt~111COBOL~Sourcen~Test_02400.cbl (2023-04-20 ** :00249: // 00249: ** //Projekt/111COBOL/Sourcen/Test_02400.cbl (2023-04-20 *
* ** :00250: // 00250: * *
**--------------------------------------------------------------** :00251: // 00251: **--------------------------------------------------------------*
如你所见,生成的 Go 代码易于理解和维护。 Enno Richter 正在寻找能够发布其有价值项目的合作公司。如果你有兴趣,请给我留言或直接联系 Enno Richter
结论
通过这篇文章,我希望你能明白,市场上缺少 COBOL 程序员的问题是可以解决的。其中一个解决方案就是 COBOL-to-Go 转译器,它可能是您迁移 COBOL 时缺失的部分。
参考文献
- Enno Richter 软件:https://www.richter-software.de
- COBOL-to-Go: https://www.richter-software.de/fileadmin/pdf/COBOL-to-Go_Marketing_Folien_Web_Deutsch.pdf
- GnuCOBOL: https://gnucobol.sourceforge.io
- COBOL 编程课程:https://openmainframeproject.org/projects/cobol-programming-course
封面照片由 Pete Linforth 从 Pixabay 拍摄。